package org.hgvc.webapp.ets.spring.service;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.apache.log4j.Logger;
import org.hgvc.webapp.ets.bo.ActionBulletin;
import org.hgvc.webapp.ets.bo.AdvancePayment;
import org.hgvc.webapp.ets.bo.Agent;
import org.hgvc.webapp.ets.bo.AgentCommission;
import org.hgvc.webapp.ets.bo.Agreement;
import org.hgvc.webapp.ets.bo.AgreementAccount;
import org.hgvc.webapp.ets.bo.AgreementControl;
import org.hgvc.webapp.ets.bo.AgreementTransferlog;
import org.hgvc.webapp.ets.bo.CommissionSchemaPaymentRange;
import org.hgvc.webapp.ets.bo.DocCheckList;
import org.hgvc.webapp.ets.bo.DocControl;
import org.hgvc.webapp.ets.bo.DocSubmission;
import org.hgvc.webapp.ets.bo.DownPaymentInstallmentSchema;
import org.hgvc.webapp.ets.bo.Finance;
import org.hgvc.webapp.ets.bo.InstallmentSchema;
import org.hgvc.webapp.ets.bo.Inventory;
import org.hgvc.webapp.ets.bo.Invoice;
import org.hgvc.webapp.ets.bo.InvoiceDtl;
import org.hgvc.webapp.ets.bo.Member;
import org.hgvc.webapp.ets.bo.MemberBooking;
import org.hgvc.webapp.ets.bo.MemberComp;
import org.hgvc.webapp.ets.bo.MemberInd;
import org.hgvc.webapp.ets.bo.MemberIndAcct;
import org.hgvc.webapp.ets.bo.MemberInstallmentPlan;
import org.hgvc.webapp.ets.bo.MemberPaymentPlan;
import org.hgvc.webapp.ets.bo.MemberPointEntitle;
import org.hgvc.webapp.ets.bo.MemberScheduleScheme;
import org.hgvc.webapp.ets.bo.MemberTransaction;
import org.hgvc.webapp.ets.bo.MemberTransactionEntitlement;
import org.hgvc.webapp.ets.bo.Membership;
import org.hgvc.webapp.ets.bo.MembershipChangeLog;
import org.hgvc.webapp.ets.bo.MicTask;
import org.hgvc.webapp.ets.bo.PartnerProduct;
import org.hgvc.webapp.ets.bo.Payment;
import org.hgvc.webapp.ets.bo.PaymentDtl;
import org.hgvc.webapp.ets.bo.PointMembershipMap;
import org.hgvc.webapp.ets.bo.StandingInstruction;
import org.hgvc.webapp.ets.constant.ActionBulletinConstant;
import org.hgvc.webapp.ets.constant.AgentConstant;
import org.hgvc.webapp.ets.constant.AgreementConstant;
import org.hgvc.webapp.ets.constant.CommonConstant;
import org.hgvc.webapp.ets.constant.MemberConstant;
import org.hgvc.webapp.ets.constant.MembershipConstant;
import org.hgvc.webapp.ets.constant.PaymentConstant;
import org.hgvc.webapp.ets.constant.SystemConstant;
import org.hgvc.webapp.ets.jsf.beans.admin.AdminAgreementTerminateBean;
import org.hgvc.webapp.ets.jsf.beans.finance.MemberPaymentBean;
import org.hgvc.webapp.ets.jsf.beans.member.MemberAgreementTransferBean;
import org.hgvc.webapp.ets.spring.dao.AdminHbmDao;
import org.hgvc.webapp.ets.spring.dao.AgreementHbmDao;
import org.hgvc.webapp.ets.spring.dao.FinanceHbmDao;
import org.hgvc.webapp.ets.spring.dao.MemberHbmDao;
import org.jocsb.base.bo.User;
import org.jocsb.base.bo.UserRole;
import org.jocsb.base.exception.BaseException;
import org.jocsb.base.spring.service.EmailManager;
import org.jocsb.base.util.DateUtil;
import org.jocsb.base.util.NumberUtil;
import org.jocsb.base.util.SpringUtils;
import org.jocsb.base.util.SystemUtil;

import com.j6.framework.util.CollectionUtil;

public class MemberServiceImpl implements MemberService {

	private MemberHbmDao dao;
	private FinanceService financeService;
	private EmailManager emailManager;
	private AdminHbmDao adminDao;
	private MasterSetupService setupService;
	private AdminService adminService;
	private SystemService systemService;
	private AgentService agentService;
	private FinanceHbmDao financeDao;
	private AgreementHbmDao agreementDao;
	private TerminateProcService terminateProcService;
	
	private static final Logger log = Logger.getLogger(MemberServiceImpl.class);

	public void setAgentService(AgentService agentService) {
		this.agentService = agentService;
	}

	public void setSystemService(SystemService systemService) {
		this.systemService = systemService;
	}

	public void setAdminService(AdminService adminService) {
		this.adminService = adminService;
	}

	public void setSetupService(MasterSetupService setupService) {
		this.setupService = setupService;
	}

	public EmailManager getEmailManager() {
		return emailManager;
	}

	public void setEmailManager(EmailManager emailManager) {
		this.emailManager = emailManager;
	}

	public AdminHbmDao getAdminDao() {
		return adminDao;
	}

	public void setAdminDao(AdminHbmDao adminDao) {
		this.adminDao = adminDao;
	}

	public FinanceService getFinanceService() {
		return financeService;
	}

	public void setFinanceService(FinanceService financeService) {
		this.financeService = financeService;
	}

	public MemberHbmDao getDao() {
		return dao;
	}

	public void setDao(MemberHbmDao dao) {
		this.dao = dao;
	}

	public String getMembershipName(Member member) throws BaseException {
		String memberName = "";
		try {
			if (member.getMemberType().equalsIgnoreCase(CommonConstant.MEMBER_TYPE_IND)) {
				MemberInd memberInd = dao.getMemberIndByMemberId(member.getMemberId());
				memberName = memberInd.getNameAsIcPassport();
			} else {
				MemberComp memberComp = dao.getMemberCompByMemberId(member.getMemberId());
				memberName = memberComp.getCompName();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "getMembershipName()" }));
		}
		return memberName;
	}

	public void reActivateUserAccount(User userP) throws BaseException {
		try {
			User user = (User) dao.getObject(User.class, userP.getUserId());
			user.setStatus(CommonConstant.STATUS_YES);
			dao.update(user);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "reActivateUserAccount()" }));
		}
	}

	// -------Added By Jacky 23-Nov-2008 1457-------
	public void reserveMemberPoint(String agreementId, Integer totalPointsReserved) throws BaseException {
		try {
			Integer availableReservedPoints = totalPointsReserved;
			// Modified by Jacky 26-Nov-2008 1929
			// List<MemberPointEntitle> list = dao.getMemberPointEntitleList(agreementId);
			List<MemberPointEntitle> list = dao.getMemberPointEntitleActiveList(agreementId);
			for (MemberPointEntitle mpe : list) {
				if (mpe.getPoint().intValue() < availableReservedPoints) {
					mpe.setReservedPoint(mpe.getPoint());
					availableReservedPoints = availableReservedPoints - mpe.getPoint();
				} else {
					mpe.setReservedPoint(availableReservedPoints);
					availableReservedPoints = 0;
				}
				dao.update(mpe);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "reserveMemberPoint()" }));
		}
	}

	public void cancelMemberPoint(String agreementId, Integer totalPointsReserved) throws BaseException {
		try {
			Integer availableReservedPoints = totalPointsReserved;
			// Modified by Jacky 26-Nov-2008 1927
			// List<MemberPointEntitle> list = dao.getMemberPointEntitleList(agreementId);
			List<MemberPointEntitle> list = dao.getMemberPointEntitleActiveList(agreementId);
			for (MemberPointEntitle mpe : list) {
				if (mpe.getPoint().intValue() < availableReservedPoints) {
					mpe.setReservedPoint(mpe.getReservedPoint() - mpe.getPoint());
					availableReservedPoints = availableReservedPoints - mpe.getPoint();
				} else {
					mpe.setReservedPoint(mpe.getReservedPoint() - availableReservedPoints);
					availableReservedPoints = 0;
				}
				dao.update(mpe);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "cancelMemberPoint()" }));
		}
	}

	public void deductMemberPoint(String agreementId, Integer totalPointsDeducted) throws BaseException {
		try {
			Integer availableDeductedPoints = totalPointsDeducted;
			// Modified by Jacky 26-Nov-2008 1927
			// List<MemberPointEntitle> list = dao.getMemberPointEntitleList(agreementId);
			List<MemberPointEntitle> list = dao.getMemberPointEntitleActiveList(agreementId);
			for (MemberPointEntitle mpe : list) {
				if (mpe.getPoint().intValue() < availableDeductedPoints) {
					mpe.setPoint(new Integer(0));
					mpe.setReservedPoint(mpe.getReservedPoint() - mpe.getPoint());
					availableDeductedPoints = availableDeductedPoints - mpe.getPoint();
				} else {
					mpe.setReservedPoint(mpe.getReservedPoint() - availableDeductedPoints);
					availableDeductedPoints = 0;
				}
				dao.update(mpe);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "deductMemberPoint()" }));
		}
	}

	public void validateMemberPoint(String agreementId, Integer pointRequired) throws BaseException {
		try {
			Integer entitlementPoints = dao.getTotalMemberEntitlementPoints(agreementId);
			Integer reservedPoints = dao.getTotalMemberReservedPoints(agreementId);

			if (entitlementPoints == null)
				throw new BaseException(SpringUtils.getMessage("error.entitlement.point.expired", new Object[] {}));

			Integer balancePoints = entitlementPoints - reservedPoints;
			// System.out.println("---balancePoints="+balancePoints);
			// System.out.println("---pointRequired="+pointRequired);
			if (balancePoints < pointRequired)
				throw new BaseException(SpringUtils.getMessage("error.insufficient.booking.point", new Object[] {
						"Entitlement", balancePoints, pointRequired }));
		} catch (BaseException be) {
			throw be;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "validateMemberPoint()" }));
		}
	}

	public void systemAutoProspectConversion() throws BaseException {
		try {
			log.debug("invoke -> systemAutoProspectConversion()");

			List<Member> list = dao.getPropectPendingMemberList();
			User systemUser = (User) dao.getObject(User.class, "0");

			for (Member member : list) {
				String membershipNo = generatePreMembershipNo(member);
				member.setMembershipNo(membershipNo);
				memberConversion(member, systemUser);
			}

			if (list.size() == 0)
				log.debug("No pending prospect in the queues");

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "systemAutoProspectConversion()" }));
		} finally {
			// Nothing to do
		}
	}

	public List<Member> getMemberList() throws BaseException {
		try {
			return dao.getMemberList();
		} catch (Exception be) {
			be.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.member", new Object[] {}));
		}
	}

	public List<MemberInd> getMemberIndList(String membershipNo, String memberName, String icNo) throws BaseException {
		try {
			return dao.getMemberInvList(membershipNo, memberName, icNo);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[] { MemberInd.class
					.getSimpleName() }));
		}
	}

	public void editMemberComp(Member member, MemberComp memberComp) throws BaseException {
		try {
			dao.update(member);
			dao.update(memberComp);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.edit.corporate.member", new Object[] {}));
		}
	}

	public void editMemberIndAcct(Member member, MemberInd memberInd, MemberIndAcct memberIndAcct) throws BaseException {
		try {
			dao.update(member);
			dao.update(memberInd);
			dao.update(memberIndAcct);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.edit.individual.member", new Object[] {}));
		}

	}

	public MemberComp getMemberCompByMemberId(String memberId) throws BaseException {
		try {
			return dao.getMemberCompByMemberId(memberId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.corporate.member", new Object[] {}));
		}
	}

	public MemberIndAcct getMemberIndAcctByMemberId(String memberId) throws BaseException {
		try {
			return dao.getMemberIndAcctByMemberId(memberId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.invdividual.member", new Object[] {}));
		}
	}

	public void deleteMemberList(List<Member> memberList, User user) throws BaseException {
		try {

			for (Member me : memberList) {
				if (me.isMarkAsAction()) {
					if (me.getMemberType().equalsIgnoreCase(CommonConstant.MEMBER_TYPE_COMP)) {
						MemberComp comp = dao.getMemberCompByMemberId(me.getMemberId());
						comp.setIsDeleted(CommonConstant.IS_DELETED);
						dao.update(comp);
					} else {
						MemberIndAcct acct = dao.getMemberIndAcctByMemberId(me.getMemberId());
						acct.setIsDeleted(CommonConstant.IS_DELETED);
						dao.update(acct);
						MemberInd ind = acct.getMemberInd();
						ind.setIsDeleted(CommonConstant.IS_DELETED);
						dao.update(ind);
					}
					me.setIsDeleted(CommonConstant.IS_DELETED);
					dao.update(me);
				}
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.delete.member", new Object[] {}));
		}

	}

	public void createMemberPaymentPlan(MemberPaymentPlan payment, List<MemberInstallmentPlan> list, Member member)
			throws BaseException {
		try {
			member.setStatus(CommonConstant.MEMBER_COMPLETE_PAYMENTPLAN_STATUS);
			member.setModifiedBy(payment.getCreatedBy());
			member.setModifiedDate(new Date());
			dao.update(member);
			dao.save(payment);
			for (MemberInstallmentPlan plan : list) {
				plan.setMemberPaymentPlan(payment);
				dao.save(plan);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.create.memeber.installment.plan", new Object[] {}));
		}
	}

	public MemberPaymentPlan getMemberPaymentPlanInfo(Member member) throws BaseException {
		try {

			MemberPaymentPlan plan = dao.getMemberPaymentPlanByMemberId(member.getMemberId());
			List<MemberInstallmentPlan> planList = dao.getMemberInstallmentPlanByPlanId(plan.getMemberPaymentPlanId());
			plan.setList(planList);

			return plan;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.payment.plan.info", new Object[] {}));
		}
	}

	public List<MemberInstallmentPlan> getMemberInstallmentPlanListByMemberId(String memberId) throws BaseException {
		try {
			return dao.getMemberInstallmentPlanListByMemberId(memberId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object",
					new Object[] { MemberInstallmentPlan.class.getSimpleName() }));
		}
	}

	// alan start
	public Payment memberAddNewAgreement(Member member, StandingInstruction si, User createdUser, Payment payment,
			PaymentDtl paymentDtl, Agreement agreement, double actualPayment) throws BaseException {
		try {

			agreement.setCreatedBy(createdUser);
			agreement.setCreatedDate(new Date());
			agreement.setIsDeleted(CommonConstant.NOT_DELETED);
			agreement.setMember(member);
			dao.save(agreement);

			Finance finance = new Finance();
			finance.setCreatedBy(createdUser);
			finance.setCreatedDate(new Date());
			finance.setIsDeleted(CommonConstant.NOT_DELETED);
			finance.setAgreement(agreement);
			dao.save(finance);

			payment = generateDepositMemberInvoice(finance, createdUser, payment, paymentDtl, agreement, actualPayment);

			si.setCreatedBy(createdUser);
			si.setCreatedDate(new Date());
			si.setIsDeleted(CommonConstant.NOT_DELETED);
			si.setMember(member);
			si.setPayment(payment);
			dao.save(agreement);

			AgreementAccount account = new AgreementAccount();
			account.setPay(actualPayment);
			account.setAgreement(agreement);
			account.setCreatedBy(createdUser);
			account.setCreatedDate(new Date());
			account.setIsDeleted(CommonConstant.NOT_DELETED);
			dao.save(account);

			if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_DEPOSIT_PACKAGE)) {
				generateDownPaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement
						.getDownPaymentInstallmentSchema(), agreement, finance, createdUser);
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, createdUser);
			} else if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_PACKAGE)) {
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, createdUser);
			}

			ActionBulletin ab = new ActionBulletin();
			ab.setActionBean("");// TODO
			ab.setActionMethod("");// TODO
			ab.setActionNo(SystemUtil.getUniqueCode());
			ab.setActionParam1(payment.getPaymentId());
			ab.setActionNav("");// TODO
			ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			ab.setCreatedDate(new Date());
			ab.setIsDeleted(CommonConstant.NOT_DELETED);
			ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			ab.setActionCode(SpringUtils.getMessage(ActionBulletinConstant.VIEW_MEMBER_PAYMENT_ACTION_CODE,
					new Object[] { payment.getReceiptNo() }));
			systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);

			return payment;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.create.new.agreement", new Object[] {}));
		}
	}
	
	public Payment createNewAgreement(Member member, List<MemberIndAcct> list,
			User createdUser, Payment payment, PaymentDtl paytmentDtl, StandingInstruction instruction,
			Agreement agreement, double actualPayment ) throws BaseException {
		try {

//			// validate by ic-no
//			List<MemberInd> clist = dao.getMemberIndByIcNo(memberInd.getNewIcNo());
//			if (clist != null && clist.size() > 0) {
//				throw new BaseException(SpringUtils.getMessage("error.duplicate.individual.member", new Object[] {}));
//			}
//
//			member.setCreatedBy(createdUser);
//			member.setCreatedDate(new Date());
//			member.setIsDeleted(CommonConstant.NOT_DELETED);
//			member.setMemberType(CommonConstant.MEMBER_TYPE_IND);
//			member.setStatus(MemberConstant.MEMBER_STATUS_PORSPECT_PENDING_ACK_PAYMENT);
//			// member.setPaymentStatus(MemberConstant.MEMBER_PAYMENT_STATUS_PENDING_ACK_DEPOSIT);
//			member.setEmail(memberInd.getEmail());
//			String no = getDocumentNo(CommonConstant.DOC_TYPE_PROSPECT_REG);
//			member.setMemberRegNo(no);
//
//			User user = adminService.createNewUserWithRole(member.getEmail(), SystemConstant.DEFAULT_PASSWORD,
//					SystemConstant.PROSPECT_MEMBER_ROLE, SystemConstant.SYSTEM_USER);
//			dao.save(user);
//
//			member.setLoginUser(user);
//			// member.setIcno(memberInd.getNewIcNo());
//			dao.save(member);
//
//			memberInd.setCreatedBy(createdUser);
//			memberInd.setCreatedDate(new Date());
//			memberInd.setIsDeleted(CommonConstant.NOT_DELETED);
//			memberInd.setMember(member);
//			dao.save(memberInd);
//
//			for (MemberIndAcct acct : list) {
//				acct.setCreatedBy(createdUser);
//				acct.setCreatedDate(new Date());
//				acct.setIsDeleted(CommonConstant.NOT_DELETED);
//				acct.setMemberInd(memberInd);
//				dao.save(acct);
//			}

			Membership membership = (Membership) dao.getObject(Membership.class, agreement.getMembership()
					.getMembershipId());
			if (membership.getMembershipType().equalsIgnoreCase(MembershipConstant.MEMBERSHIP_TYPE_EVEN_OR_ODD)) {
				int year = DateUtil.getCurrentYear(new Date());
				if (NumberUtil.isEvenNumber(year))
					agreement.setMembershipType(MembershipConstant.MEMBERSHIP_TYPE_EVEN);
				else
					agreement.setMembershipType(MembershipConstant.MEMBERSHIP_TYPE_ODD);
			} else {
				agreement.setMembershipType(membership.getMembershipType());
			}

			agreement.setCreatedBy(createdUser);
			agreement.setCreatedDate(new Date());
			agreement.setIsDeleted(CommonConstant.NOT_DELETED);
			agreement.setMember(member);

			MemberScheduleScheme m = null;
			if (agreement.getInstallmentSchema() != null) {
				m = new MemberScheduleScheme();
				m.setAgreement(agreement);
				m.setCreatedBy(createdUser);
				m.setCreatedDate(new Date());
				m.setInstalledMonth(0);
				m.setInterestRate(agreement.getInstallmentSchema().getInterestRate());
				m.setModifiedBy(createdUser);
				m.setModifiedDate(new Date());
				double price = agreement.getMembership().getMembershipFeeDbl()
						* (((100 - agreement.getInstallmentSchema().getDepositPercent()) / 100));
				m.setTotalPrice(price);
				dao.save(m);
				agreement.setMemberScheduleScheme(m);
			}
			dao.save(agreement);
			if (agreement.getInstallmentSchema() != null) {
				m.setAgreement(agreement);
				dao.update(m);
			}

			Finance finance = new Finance();
			finance.setCreatedBy(createdUser);
			finance.setCreatedDate(new Date());
			finance.setIsDeleted(CommonConstant.NOT_DELETED);
			finance.setAgreement(agreement);
			dao.save(finance);

			payment = generateDepositMemberInvoice(finance, createdUser, payment, paytmentDtl, agreement, actualPayment);

			AgreementAccount account = new AgreementAccount();
			account.setPay(actualPayment);
			account.setAgreement(agreement);
			account.setCreatedBy(createdUser);
			account.setCreatedDate(new Date());
			account.setIsDeleted(CommonConstant.NOT_DELETED);
			dao.save(account);

			User attnUser = null;
			if (agreement.getRegType().equalsIgnoreCase(AgreementConstant.AGREEMENT_GIFT_REG)) {
				attnUser = createdUser;
			} else {
				attnUser = member.getLoginUser();
			}

			if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_DEPOSIT_PACKAGE)) {
				generateDownPaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement
						.getDownPaymentInstallmentSchema(), agreement, finance, attnUser);
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, attnUser);
			} else if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_PACKAGE)) {
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, attnUser);
			}

			if (instruction != null) {
				instruction.setMember(member);
				instruction.setCreatedBy(createdUser);
				instruction.setCreatedDate(new Date());
				instruction.setIsDeleted(CommonConstant.NOT_DELETED);
				instruction.setPayment(payment);
				dao.save(instruction);
			}

			if (member.getRegistrationType().equalsIgnoreCase(MemberConstant.MEMBER_REG_ONLINE)) {

				// send email notification
				/*
				 * emailManager.sendEmail("You're have successfully become a Prospect Member.\n " + "This is your
				 * temporary login username & password:\n" + "Username:"+memberInd.getNewIcNo()+"\n" +
				 * "Password:"+SystemConstant.DEFAULT_PASSWORD+"\n" , memberInd.getEmail(), "Registration Succesfully",
				 * SystemConstant.SYSTEM_EMAIL);
				 */
			}
			// create action bulletin for finance module
			/*
			 * List<User> usrList = adminDao.getUserByRole(SystemConstant.FINANCE_ADMIN_ROLE.getRoleId()); for(User
			 * usr:usrList){
			 */
			ActionBulletin ab = new ActionBulletin();
			ab.setActionBean(MemberPaymentBean.BEAN_NAME);
			ab.setActionMethod("viewMemberPayment");
			ab.setActionNo(SystemUtil.getUniqueCode());
			ab.setActionParam1(payment.getPaymentId());
			ab.setActionParam2("newagreement");//for those already got one agreement. just indicate. use in financeservice.memberDepositPaymentClearance
			ab.setActionNav(MemberPaymentBean.NAV_VIEW_MEMBER_PAYMENT);
			ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			ab.setCreatedDate(new Date());
			ab.setIsDeleted(CommonConstant.NOT_DELETED);
			ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			ab.setActionCode(SpringUtils.getMessage(ActionBulletinConstant.VIEW_MEMBER_PAYMENT_ACTION_CODE,
					new Object[] { payment.getReceiptNo() }));
			systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);
			// }

			return payment;
		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.create.individual.member", new Object[] {}));
		}
	}

	public Payment createProspectIndividualMember(Member member, MemberInd memberInd, List<MemberIndAcct> list,
			User createdUser, Payment payment, PaymentDtl paytmentDtl, StandingInstruction instruction,
			Agreement agreement, double actualPayment) throws BaseException {
		try {

			// validate by ic-no
			List<MemberInd> clist = dao.getMemberIndByIcNo(memberInd.getNewIcNo());
			if (clist != null && clist.size() > 0) {
				throw new BaseException(SpringUtils.getMessage("error.duplicate.individual.member", new Object[] {}));
			}

			member.setCreatedBy(createdUser);
			member.setCreatedDate(new Date());
			member.setIsDeleted(CommonConstant.NOT_DELETED);
			member.setMemberType(CommonConstant.MEMBER_TYPE_IND);
			member.setStatus(MemberConstant.MEMBER_STATUS_PORSPECT_PENDING_ACK_PAYMENT);
			// member.setPaymentStatus(MemberConstant.MEMBER_PAYMENT_STATUS_PENDING_ACK_DEPOSIT);
			member.setEmail(memberInd.getEmail());
			String no = getDocumentNo(CommonConstant.DOC_TYPE_PROSPECT_REG);
			member.setMemberRegNo(no);

			User user = adminService.createNewUserWithRole(member.getEmail(), SystemConstant.DEFAULT_PASSWORD,
					SystemConstant.PROSPECT_MEMBER_ROLE, SystemConstant.SYSTEM_USER);
			dao.save(user);

			member.setLoginUser(user);
			// member.setIcno(memberInd.getNewIcNo());
			dao.save(member);

			memberInd.setCreatedBy(createdUser);
			memberInd.setCreatedDate(new Date());
			memberInd.setIsDeleted(CommonConstant.NOT_DELETED);
			memberInd.setMember(member);
			dao.save(memberInd);

			for (MemberIndAcct acct : list) {
				acct.setCreatedBy(createdUser);
				acct.setCreatedDate(new Date());
				acct.setIsDeleted(CommonConstant.NOT_DELETED);
				acct.setMemberInd(memberInd);
				dao.save(acct);
			}

			Membership membership = (Membership) dao.getObject(Membership.class, agreement.getMembership()
					.getMembershipId());
			if (membership.getMembershipType().equalsIgnoreCase(MembershipConstant.MEMBERSHIP_TYPE_EVEN_OR_ODD)) {
				int year = DateUtil.getCurrentYear(new Date());
				if (NumberUtil.isEvenNumber(year))
					agreement.setMembershipType(MembershipConstant.MEMBERSHIP_TYPE_EVEN);
				else
					agreement.setMembershipType(MembershipConstant.MEMBERSHIP_TYPE_ODD);
			} else {
				agreement.setMembershipType(membership.getMembershipType());
			}

			agreement.setCreatedBy(createdUser);
			agreement.setCreatedDate(new Date());
			agreement.setIsDeleted(CommonConstant.NOT_DELETED);
			agreement.setMember(member);

			MemberScheduleScheme m = null;
			if (agreement.getInstallmentSchema() != null) {
				m = new MemberScheduleScheme();
				m.setAgreement(agreement);
				m.setCreatedBy(user);
				m.setCreatedDate(new Date());
				m.setInstalledMonth(0);
				m.setInterestRate(agreement.getInstallmentSchema().getInterestRate());
				m.setModifiedBy(user);
				m.setModifiedDate(new Date());
				double price = agreement.getMembership().getMembershipFeeDbl()
						* (((100 - agreement.getInstallmentSchema().getDepositPercent()) / 100));
				m.setTotalPrice(price);
				dao.save(m);
				agreement.setMemberScheduleScheme(m);
			}
			dao.save(agreement);
			if (agreement.getInstallmentSchema() != null) {
				m.setAgreement(agreement);
				dao.update(m);
			}

			Finance finance = new Finance();
			finance.setCreatedBy(createdUser);
			finance.setCreatedDate(new Date());
			finance.setIsDeleted(CommonConstant.NOT_DELETED);
			finance.setAgreement(agreement);
			dao.save(finance);

			payment = generateDepositMemberInvoice(finance, createdUser, payment, paytmentDtl, agreement, actualPayment);

			AgreementAccount account = new AgreementAccount();
			account.setPay(actualPayment);
			account.setAgreement(agreement);
			account.setCreatedBy(createdUser);
			account.setCreatedDate(new Date());
			account.setIsDeleted(CommonConstant.NOT_DELETED);
			dao.save(account);

			User attnUser = null;
			if (agreement.getRegType().equalsIgnoreCase(AgreementConstant.AGREEMENT_GIFT_REG)) {
				attnUser = createdUser;
			} else {
				attnUser = user;
			}

			if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_DEPOSIT_PACKAGE)) {
				generateDownPaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement
						.getDownPaymentInstallmentSchema(), agreement, finance, attnUser);
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, attnUser);
			} else if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_PACKAGE)) {
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, attnUser);
			}

			if (instruction != null) {
				instruction.setMember(member);
				instruction.setCreatedBy(createdUser);
				instruction.setCreatedDate(new Date());
				instruction.setIsDeleted(CommonConstant.NOT_DELETED);
				instruction.setPayment(payment);
				dao.save(instruction);
			}

			if (member.getRegistrationType().equalsIgnoreCase(MemberConstant.MEMBER_REG_ONLINE)) {

				// send email notification
				/*
				 * emailManager.sendEmail("You're have successfully become a Prospect Member.\n " + "This is your
				 * temporary login username & password:\n" + "Username:"+memberInd.getNewIcNo()+"\n" +
				 * "Password:"+SystemConstant.DEFAULT_PASSWORD+"\n" , memberInd.getEmail(), "Registration Succesfully",
				 * SystemConstant.SYSTEM_EMAIL);
				 */
			}
			// create action bulletin for finance module
			/*
			 * List<User> usrList = adminDao.getUserByRole(SystemConstant.FINANCE_ADMIN_ROLE.getRoleId()); for(User
			 * usr:usrList){
			 */
			ActionBulletin ab = new ActionBulletin();
			ab.setActionBean(MemberPaymentBean.BEAN_NAME);
			ab.setActionMethod("viewMemberPayment");
			ab.setActionNo(SystemUtil.getUniqueCode());
			ab.setActionParam1(payment.getPaymentId());
			ab.setActionNav(MemberPaymentBean.NAV_VIEW_MEMBER_PAYMENT);
			ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			ab.setCreatedDate(new Date());
			ab.setIsDeleted(CommonConstant.NOT_DELETED);
			ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			ab.setActionCode(SpringUtils.getMessage(ActionBulletinConstant.VIEW_MEMBER_PAYMENT_ACTION_CODE,
					new Object[] { payment.getReceiptNo() }));
			systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);
			// }

			return payment;
		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.create.individual.member", new Object[] {}));
		}
	}

	public Payment createProspectCompMember(Member member, MemberComp memberComp, User createdUser,
			List<MemberIndAcct> list, Payment payment, PaymentDtl paytmentDtl, StandingInstruction instruction,
			Agreement agreement, double actualPayment) throws BaseException {
		try {
			// validate by comp name
			List<MemberComp> clist = dao.getMemberCompByCompName(memberComp.getCompName().trim());
			if (clist != null && clist.size() > 0) {
				throw new BaseException(SpringUtils.getMessage("error.duplicate.corporate.member", new Object[] {}));
			}

			member.setCreatedBy(createdUser);
			member.setCreatedDate(new Date());
			member.setIsDeleted(CommonConstant.NOT_DELETED);
			member.setMemberType(CommonConstant.MEMBER_TYPE_COMP);
			member.setStatus(MemberConstant.MEMBER_STATUS_PORSPECT_PENDING_ACK_PAYMENT);
			// member.setPaymentStatus(MemberConstant.MEMBER_PAYMENT_STATUS_PENDING_ACK_DEPOSIT);
			member.setEmail(memberComp.getEmail());

			String no = getDocumentNo(CommonConstant.DOC_TYPE_PROSPECT_REG);
			member.setMemberRegNo(no);

			User user = adminService.createNewUserWithRole(member.getEmail(), SystemConstant.DEFAULT_PASSWORD,
					SystemConstant.PROSPECT_MEMBER_ROLE, SystemConstant.SYSTEM_USER);
			member.setLoginUser(user);
			member.setMembershipNo(generateMembershipNo(member));

			dao.save(member);

			memberComp.setCreatedBy(createdUser);
			memberComp.setCreatedDate(new Date());
			memberComp.setIsDeleted(CommonConstant.NOT_DELETED);
			memberComp.setMember(member);
			dao.save(memberComp);

			Membership membership = (Membership) dao.getObject(Membership.class, agreement.getMembership()
					.getMembershipId());
			if (membership.getMembershipType().equalsIgnoreCase(MembershipConstant.MEMBERSHIP_TYPE_EVEN_OR_ODD)) {
				int year = DateUtil.getCurrentYear(new Date());
				if (NumberUtil.isEvenNumber(year))
					agreement.setMembershipType(MembershipConstant.MEMBERSHIP_TYPE_EVEN);
				else
					agreement.setMembershipType(MembershipConstant.MEMBERSHIP_TYPE_ODD);
			} else {
				agreement.setMembershipType(membership.getMembershipType());
			}

			agreement.setCreatedBy(createdUser);
			agreement.setCreatedDate(new Date());
			agreement.setIsDeleted(CommonConstant.NOT_DELETED);
			agreement.setMember(member);
			MemberScheduleScheme m = null;
			if (agreement.getInstallmentSchema() != null) {
				m = new MemberScheduleScheme();
				m.setAgreement(agreement);
				m.setCreatedBy(user);
				m.setCreatedDate(new Date());
				m.setInstalledMonth(0);
				m.setInterestRate(agreement.getInstallmentSchema().getInterestRate());
				m.setModifiedBy(user);
				m.setModifiedDate(new Date());
				double price = agreement.getMembership().getMembershipFeeDbl()
						* (((100 - agreement.getInstallmentSchema().getDepositPercent()) / 100));
				m.setTotalPrice(price);
				dao.save(m);
				agreement.setMemberScheduleScheme(m);
			}
			dao.save(agreement);
			if (agreement.getInstallmentSchema() != null) {
				m.setAgreement(agreement);
				dao.update(m);
			}
			Finance finance = new Finance();
			finance.setCreatedBy(createdUser);
			finance.setCreatedDate(new Date());
			finance.setIsDeleted(CommonConstant.NOT_DELETED);
			finance.setAgreement(agreement);
			dao.save(finance);

			for (MemberIndAcct acct : list) {
				acct.setCreatedBy(createdUser);
				acct.setCreatedDate(new Date());
				acct.setIsDeleted(CommonConstant.NOT_DELETED);
				acct.setMemberComp(memberComp);
				dao.save(acct);
			}

			payment = generateDepositMemberInvoice(finance, createdUser, payment, paytmentDtl, agreement, actualPayment);
			AgreementAccount account = new AgreementAccount();
			account.setPay(actualPayment);
			account.setAgreement(agreement);
			account.setCreatedBy(createdUser);
			account.setCreatedDate(new Date());
			account.setIsDeleted(CommonConstant.NOT_DELETED);
			dao.save(account);

			User attnUser = null;
			if (agreement.getRegType().equalsIgnoreCase(AgreementConstant.AGREEMENT_GIFT_REG)) {
				attnUser = createdUser;
			} else {
				attnUser = user;
			}

			if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_DEPOSIT_PACKAGE)) {
				generateDownPaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement
						.getDownPaymentInstallmentSchema(), agreement, finance, attnUser);
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, attnUser);
			} else if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_PACKAGE)) {
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, attnUser);
			}

			if (instruction != null) {
				instruction.setCreatedBy(createdUser);
				instruction.setCreatedDate(new Date());
				instruction.setIsDeleted(CommonConstant.NOT_DELETED);
				instruction.setMember(member);
				instruction.setPayment(payment);
				dao.save(instruction);
			}

			if (member.getRegistrationType().equalsIgnoreCase(MemberConstant.MEMBER_REG_ONLINE)) {
				// send email notification
				/*
				 * emailManager.sendEmail("You're have successfully become a Prospect Member.\n " + "This is your
				 * temporary login username & password:\n" + "Username:"+memberComp.getCompName().trim()+"\n" +
				 * "Password:"+SystemConstant.DEFAULT_PASSWORD+"\n" , memberComp.getEmail(), "Registration Succesfully",
				 * SystemConstant.SYSTEM_EMAIL);
				 */
			}
			// create action bulletin for finance module
			/*
			 * List<User> usrList = adminDao.getUserByRole(SystemConstant.FINANCE_ADMIN_ROLE.getRoleId()); for(User
			 * usr:usrList){
			 */
			ActionBulletin ab = new ActionBulletin();
			ab.setActionBean(MemberPaymentBean.BEAN_NAME);
			ab.setActionMethod("viewMemberPayment");
			ab.setActionParam1(payment.getPaymentId());
			ab.setActionNo(SystemUtil.getUniqueCode());
			ab.setActionNav(MemberPaymentBean.NAV_VIEW_MEMBER_PAYMENT);
			ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			ab.setCreatedDate(new Date());
			ab.setIsDeleted(CommonConstant.NOT_DELETED);
			ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			ab.setActionCode(SpringUtils.getMessage(ActionBulletinConstant.VIEW_MEMBER_PAYMENT_ACTION_CODE,
					new Object[] { payment.getReceiptNo() }));
			systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);
			// }

			return payment;
		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.create.corporate.member", new Object[] {}));
		}
	}
	
	public void createMemberAgreement(Member member, Agreement agreement, double actualPayment, User createdUser,
			Payment payment, PaymentDtl paytmentDtl, StandingInstruction instruction) throws BaseException {
		try {
			agreement.setCreatedBy(createdUser);
			agreement.setCreatedDate(new Date());
			agreement.setIsDeleted(CommonConstant.NOT_DELETED);
			agreement.setMember(member);
			dao.save(agreement);

			Finance finance = new Finance();
			finance.setCreatedBy(createdUser);
			finance.setCreatedDate(new Date());
			finance.setIsDeleted(CommonConstant.NOT_DELETED);
			finance.setAgreement(agreement);
			dao.save(finance);

			payment = generateDepositMemberInvoice(finance, createdUser, payment, paytmentDtl, agreement, actualPayment);
			AgreementAccount account = new AgreementAccount();
			account.setPay(actualPayment);
			account.setAgreement(agreement);
			account.setCreatedBy(createdUser);
			account.setCreatedDate(new Date());
			account.setIsDeleted(CommonConstant.NOT_DELETED);
			dao.save(account);

			User attnUser = createdUser;

			if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_DEPOSIT_PACKAGE)) {
				generateDownPaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement
						.getDownPaymentInstallmentSchema(), agreement, finance, attnUser);
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, attnUser);
			} else if (agreement.getPaymentType().equalsIgnoreCase(
					AgreementConstant.AGREEMENT_PAYMENT_INSTALLMENT_PACKAGE)) {
//				generatePaymentInstallmentInvoice(agreement.getInstallmentSchema(), agreement, finance, attnUser);
			}

			if (instruction != null) {
				instruction.setCreatedBy(createdUser);
				instruction.setCreatedDate(new Date());
				instruction.setIsDeleted(CommonConstant.NOT_DELETED);
				instruction.setMember(member);
				instruction.setPayment(payment);
				dao.save(instruction);
			}

			ActionBulletin ab = new ActionBulletin();
			ab.setActionBean(MemberPaymentBean.BEAN_NAME);
			ab.setActionMethod("viewMemberPayment");
			ab.setActionParam1(payment.getPaymentId());
			ab.setActionNo(SystemUtil.getUniqueCode());
			ab.setActionNav(MemberPaymentBean.NAV_VIEW_MEMBER_PAYMENT);
			ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			ab.setCreatedDate(new Date());
			ab.setIsDeleted(CommonConstant.NOT_DELETED);
			ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			ab.setActionCode(SpringUtils.getMessage(ActionBulletinConstant.VIEW_MEMBER_PAYMENT_ACTION_CODE,
					new Object[] { payment.getReceiptNo() }));
			systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);

		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("", new Object[] {}));
		}

	}

	public Payment memberMakePayment(Agreement agreement, User user, double amt, double actualAmt, Invoice invoice,
			InvoiceDtl invoiceDtl) throws BaseException {

		try {

			Finance finance = dao.getFinanceByMembertId(agreement.getMember().getMemberId());

			Payment payment = new Payment();
			payment.setFinance(finance);
			payment.setPaymentDate(new Date());
			payment.setRefId(agreement.getAgreementId());
			payment.setCreatedBy(user);
			payment.setCreatedDate(new Date());
			payment.setPaymentDate(new Date());
			payment.setPaymentAmount(actualAmt);
			payment.setReceiptNo(financeService.getDocumentNo(CommonConstant.DOC_TYPE_RECEIPT));
			payment.setIsDeleted(CommonConstant.NOT_DELETED);
			payment.setStatus(PaymentConstant.PAYMENT_STATUS_PENDING);
			dao.save(payment);

			PaymentDtl paymentDtl = new PaymentDtl();
			paymentDtl.setPayment(payment);
			// paymentDtl.setInvoiceDtl(invoiceDtl);
			paymentDtl.setCreatedBy(user);
			paymentDtl.setCreatedDate(new Date());
			paymentDtl.setIsDeleted(CommonConstant.NOT_DELETED);
			paymentDtl.setAmount(actualAmt);
			dao.save(paymentDtl);

			if (payment.getPaymentAmount().doubleValue() > actualAmt) {
				invoiceDtl.setPaidAmount(invoice.getInvoiceAmount());
				// insert advance payment
				AdvancePayment ap = new AdvancePayment();
				double d = actualAmt - payment.getPaymentAmount().doubleValue();
				ap.setAmount(d);
				ap.setCreatedBy(user);
				ap.setCreatedDate(new Date());
				ap.setIsDeleted(CommonConstant.NOT_DELETED);
				ap.setFinance(finance);
				ap.setPayment(payment);
				dao.save(ap);
			} else {
				invoiceDtl.setPaidAmount(actualAmt);
			}

			invoice.setPayment(payment);
			dao.update(invoice);

			ActionBulletin ab = new ActionBulletin();
			ab.setActionBean(MemberPaymentBean.BEAN_NAME);
			ab.setActionMethod("viewMemberPayment");
			ab.setActionParam1(payment.getPaymentId());
			ab.setActionNo(SystemUtil.getUniqueCode());
			ab.setActionNav(MemberPaymentBean.NAV_VIEW_MEMBER_PAYMENT);
			ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			ab.setCreatedDate(new Date());
			ab.setIsDeleted(CommonConstant.NOT_DELETED);
			ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			ab.setActionCode(SpringUtils.getMessage(ActionBulletinConstant.VIEW_MEMBER_PAYMENT_ACTION_CODE,
					new Object[] { payment.getReceiptNo() }));
			systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);
			return payment;

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException("");
		}

	}

	private Payment generateDepositMemberInvoice(Finance finance, User user, Payment payment, PaymentDtl paymentDtl,
			Agreement agreement, double actualAmt) throws Exception {

		String newInvoiceNo = financeService.getDocumentNo(CommonConstant.DOC_TYPE_INVOICE);

		payment.setFinance(finance);
		payment.setPaymentDate(new Date());
		payment.setRefId(agreement.getAgreementId());
		payment.setCreatedBy(user);
		payment.setCreatedDate(new Date());
		payment.setPaymentDate(new Date());
		payment.setPaymentAmount(actualAmt);
		payment.setReceiptNo(financeService.getDocumentNo(CommonConstant.DOC_TYPE_RECEIPT));
		payment.setIsDeleted(CommonConstant.NOT_DELETED);
		payment.setStatus(PaymentConstant.PAYMENT_STATUS_PENDING);
		dao.save(payment);

		paymentDtl.setPayment(payment);
		// paymentDtl.setInvoiceDtl(invoiceDtl);
		paymentDtl.setCreatedBy(user);
		paymentDtl.setCreatedDate(new Date());
		paymentDtl.setIsDeleted(CommonConstant.NOT_DELETED);
		paymentDtl.setAmount(actualAmt);
		dao.save(paymentDtl);

		// generate invoice
		Invoice invoice = new Invoice();
		invoice.setCreatedBy(user);
		invoice.setCreatedDate(new Date());
		invoice.setInvoiceAmount(actualAmt);
		invoice.setInvoiceDate(new Date());
		invoice.setInvoiceNo(newInvoiceNo);
		invoice.setIsDeleted(CommonConstant.NOT_DELETED);
		invoice.setRefId(agreement.getAgreementId());
		invoice.setFinance(finance);
		invoice.setPayment(payment);
		dao.save(invoice);

		// generate invoice dtl
		InvoiceDtl invoiceDtl = new InvoiceDtl();
		invoiceDtl.setInvoice(invoice);
		invoiceDtl.setCreatedBy(user);
		invoiceDtl.setCreatedDate(new Date());
		invoiceDtl.setIsDeleted(CommonConstant.NOT_DELETED);
		invoiceDtl.setItemAmount(invoice.getInvoiceAmount());
		invoiceDtl.setItemType(CommonConstant.INVOICE_TYPE_DEPOSIT);
		invoiceDtl.setStatus(CommonConstant.INVOICE_STATUS_ACTIVE);
		invoiceDtl.setItemDesc(CommonConstant.INVOICE_DEPOSIT_ITEM_DESC);

		if (payment.getPaymentAmount().doubleValue() > actualAmt) {
			invoiceDtl.setPaidAmount(invoice.getInvoiceAmount());
			// insert advance payment
			AdvancePayment ap = new AdvancePayment();
			double d = actualAmt - payment.getPaymentAmount().doubleValue();
			ap.setAmount(d);
			ap.setCreatedBy(user);
			ap.setCreatedDate(new Date());
			ap.setIsDeleted(CommonConstant.NOT_DELETED);
			ap.setFinance(finance);
			ap.setPayment(payment);
			dao.save(ap);
		} else {
			invoiceDtl.setPaidAmount(actualAmt);
		}
		dao.save(invoiceDtl);

		return payment;
	}

	/*
	 * private Date generateCoolingPeriodEndDate(Date start,Date end)throws Exception{ //list range calendar date
	 * Calendar endCal = GregorianCalendar.getInstance(); endCal.setTime(end); List<com.ets.dbo.Calendar> cList =
	 * dao.getCalendarList(start, end); int count = cList.size(); int sum = 0; while(count>0){ int temp = count; sum
	 * +=count; endCal.add(Calendar.DAY_OF_YEAR, count); end = endCal.getTime(); cList = dao.getCalendarList(start,
	 * end); count = cList.size(); if(temp==count){ break; } } //check sat & sun int ret = 0; Calendar startCal =
	 * GregorianCalendar.getInstance(); Date loop = startCal.getTime(); for(int i=0;loop.compareTo(end)!=0;i++){
	 * startCal.add(Calendar.DAY_OF_YEAR,i); loop = startCal.getTime(); switch(startCal.get(Calendar.DAY_OF_WEEK)){ case
	 * Calendar.SATURDAY: case Calendar.SUNDAY: ret++; } }
	 * 
	 * if(ret>0){ endCal.add(Calendar.DAY_OF_YEAR, ret); end = endCal.getTime(); }
	 * 
	 * sum = ret+sum; if(sum==0){ return end; }else{ return generateCoolingPeriodEndDate(start,end); } }
	 */

	private Date generateCoolingPeriodEndDate(Date start, Date end) throws Exception {
		Calendar cal = GregorianCalendar.getInstance();
		cal.setTime(start);
		cal.add(Calendar.DAY_OF_YEAR, -1);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		start = cal.getTime();

		Calendar loopCal = GregorianCalendar.getInstance();
		loopCal.setTime(start);
		Date loop = loopCal.getTime();

		List<org.hgvc.webapp.ets.bo.Calendar> list = dao.getCalendarList();
		for (int i = 0; loop.compareTo(end) != 0; i++) {
			loop = loopCal.getTime();
			switch (loopCal.get(Calendar.DAY_OF_WEEK)) {
			case Calendar.SATURDAY:
			case Calendar.SUNDAY:
				cal.setTime(end);
				cal.add(Calendar.DAY_OF_YEAR, 1);
				end = cal.getTime();
				loopCal.add(Calendar.DAY_OF_YEAR, 1);
				continue;
			}
			for (org.hgvc.webapp.ets.bo.Calendar pcalendar : list) {
				Calendar pcal = GregorianCalendar.getInstance();
				pcal.setTime(pcalendar.getDate());
				pcal.set(Calendar.HOUR_OF_DAY, 0);
				pcal.set(Calendar.MINUTE, 0);
				pcal.set(Calendar.SECOND, 0);
				if (loop.compareTo(pcal.getTime()) == 0) {
					cal.setTime(end);
					cal.add(Calendar.DAY_OF_YEAR, 1);
					end = cal.getTime();
				}
			}
			loopCal.add(Calendar.DAY_OF_YEAR, 1);
		}
		return end;
	}

	public void generateMemberAgreement(Member member, Agreement agreement, User user, String actionNo, boolean newAgreementExistingMember)
			throws Exception {
		Agreement dbAgreement = (Agreement)dao.getObject(Agreement.class, agreement.getAgreementId());
		
		try {
			// check dupate agreement no.
			List<Agreement> aList = dao.getAgreementListByAgreementNo(agreement.getAgreetmentNo());
			if (aList != null && aList.size() > 0) {
				for (Agreement a : aList) {
					if (!a.getAgreementId().equalsIgnoreCase(agreement.getAgreementId())) {
						throw new BaseException(SpringUtils.getMessage("error.dupliate.agreement.no", new Object[] {}));
					}
				}
			}

			//
			if (member.getRegistrationType().equalsIgnoreCase(MemberConstant.MEMBER_REG_AGENT)) {

				Agent agent = member.getAgent();
				// find parent
				if (!agent.getAgentType().equalsIgnoreCase(AgentConstant.AGENT_LEVEL_1)) {
					while (!agent.getAgentType().equalsIgnoreCase(AgentConstant.AGENT_LEVEL_1)) {
						agent = (Agent) dao.getObject(Agent.class, agent.getParent().getAgentId());
					}
				}

				String agreementNo = agreement.getAgreetmentNo();
				List<AgreementControl> controlList = dao.getAgreementControlByAgentId(agent.getAgentId());

				boolean prefixFlag = false;
				boolean range = false;
				String prefix = null;
				AgreementControl pcontrol = null;
				for (AgreementControl control : controlList) {
					// check prefix
					if (agreementNo.startsWith(control.getPrefix())) {
						prefixFlag = true;
						prefix = control.getPrefix();
						pcontrol = control;
						break;
					}
				}

				if (!prefixFlag) {
					throw new BaseException(SpringUtils.getMessage("invalid.agreement.no.prefix.admin.assign",
							new Object[] {}));
				}
				agreementNo = agreementNo.substring(prefix.length());

				if (agreementNo.length() != pcontrol.getSize().intValue()) {
					throw new BaseException(SpringUtils
							.getMessage("invalid.agreement.no.admin.assign", new Object[] {}));
				}

				long no = Long.parseLong(agreementNo);

				for (AgreementControl control : controlList) {
					long start = Long.parseLong(control.getStart());
					long max = control.getMax().longValue();
					if (no >= start && no <= max) {
						range = true;
						pcontrol = control;
						break;
					}
				}

				if (agreementNo.length() != pcontrol.getSize().intValue()) {
					throw new BaseException(SpringUtils
							.getMessage("invalid.agreement.no.admin.assign", new Object[] {}));
				}

				if (!range) {
					throw new BaseException(SpringUtils
							.getMessage("invalid.agreement.no.admin.assign", new Object[] {}));
				}
			}

			// calculate cooling period according to calendar
			if (newAgreementExistingMember){
				
				// generate point 
				Membership membership = agreement.getMembership();
				List<PointMembershipMap> pointList = dao.getPointMembershipMapList(membership.getMembershipId());
				Calendar calendar = GregorianCalendar.getInstance();
				calendar.setTime(new Date());
				int year = calendar.get(Calendar.YEAR);
				calendar.add(Calendar.YEAR, 1);
				Date expiry = calendar.getTime();
				for (PointMembershipMap map : pointList) {
					MemberPointEntitle entitle = new MemberPointEntitle();
					entitle.setPoint(map.getPoint());
					entitle.setAgreement(agreement);
					entitle.setYear(new Integer(year));
					entitle.setPointCategory(map.getPointCategory());
					entitle.setCreatedBy(user);
					entitle.setCreatedDate(new Date());
					entitle.setStatus(MemberConstant.MEMBER_POINT_VALID);
					entitle.setIsDeleted(CommonConstant.NOT_DELETED);
					entitle.setExpiryDate(expiry);
					dao.save(entitle);
				}
				String newTransactionDesc = SpringUtils.getMessage(MemberConstant.TRANS_NEW_ENTITLEMENT,
						new Object[] { year });
				insertMemberTransaction(agreement.getAgreementId(), newTransactionDesc);

			}else{
				Date start = agreement.getAgreetmentDate();
				Calendar endCal = GregorianCalendar.getInstance();
				endCal.setTime(start);
				endCal.add(Calendar.DAY_OF_YEAR, agreement.getCoolingOffPeriodInt());
				Date end = endCal.getTime();
				end = generateCoolingPeriodEndDate(start, end);
				agreement.setStartCoolingPeriod(start);
				agreement.setEndCoolingPeriod(end);
				
				// update member
				member.setModifiedBy(user);
				member.setModifiedDate(new Date());
				member.setStatus(MemberConstant.MEMBER_STATUS_PROSPECT_ACK_AGREEMENT);
				// member.setStartCoolingPeriod(start);
				// member.setEndCoolingPeriod(end);
				dao.merge(member);
			}
			
			dbAgreement.setAgreetmentDate(agreement.getAgreetmentDate());
			dbAgreement.setAgreetmentNo(agreement.getAgreetmentNo());
			dbAgreement.setCreatedBy(user);
			dbAgreement.setCreatedDate(new Date());
			dbAgreement.setIsDeleted(CommonConstant.NOT_DELETED);
			dbAgreement.setStatus(AgreementConstant.AGREEMENT_STATUS_ACK);
			dbAgreement.setMember(member);
		 
			dao.update(dbAgreement);
 
			systemService.deleteActionBulletinByActionNo(actionNo);

			List<DocCheckList> list = null;
			if (member.getMemberType().equalsIgnoreCase(CommonConstant.MEMBER_TYPE_COMP)) {
				list = dao.getDocCheckListType(CommonConstant.MEMBER_TYPE_COMP);
			} else {
				list = dao.getDocCheckListType(CommonConstant.MEMBER_TYPE_IND);
			}

			for (DocCheckList doc : list) {
				DocSubmission docSub = new DocSubmission();
				docSub.setDocCheckList(doc);
				docSub.setIsDeleted(CommonConstant.NOT_DELETED);
				docSub.setCreatedBy(SystemConstant.SYSTEM_USER);
				docSub.setCreatedDate(new Date());
				docSub.setMember(member);
				dao.save(docSub);
			}

			/*
			 * ActionBulletin ab = new ActionBulletin(); ab.setActionBean(MemberPaymentBean.BEAN_NAME);
			 * ab.setActionMethod("");//TODO ab.setActionParam1(agreement.getAgreementId());
			 * ab.setCreatedBy(SystemConstant.SYSTEM_USER); ab.setCreatedDate(new Date());
			 * ab.setIsDeleted(CommonConstant.NOT_DELETED); ab.setUser(member.getLoginUser());
			 * ab.setType(CommonConstant.AB_TYPE_USER); ab.setActionCode("");//TODO dao.save(ab);
			 */

		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.generate.member.agreement", new Object[] {}));
		}
	}

	// scheduler
	/*
	 * public void prospectMemberConversionCheckListStatus()throws Exception{ try{ List<Member> members =
	 * dao.getMemberListByStatus(MemberConstant.MEMBER_STATUS_PROSPECT_ACK_AGREEMENT); Date today = new Date();
	 * for(Member member:members){ if(member.getEndCoolingPeriod().after(today)){ //update member status to checklist
	 * member.setStatus(MemberConstant.MEMBER_STATUS_PROSPECT_PENDING_CHECK_LIST);
	 * member.setModifiedBy(SystemConstant.SYSTEM_USER); member.setModifiedDate(new Date()); dao.update(member); } }
	 * }catch(Exception ex){ ex.printStackTrace(); } }
	 */

	public void prospectMemberConversionCheckListStatus(Member member, User user) throws BaseException {
		try {
			// update member status to checklist
			member.setStatus(MemberConstant.MEMBER_STATUS_PROSPECT_PENDING_CHECK_LIST);
			member.setModifiedBy(user);
			member.setModifiedDate(new Date());
			dao.update(member);
		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("", new Object[] {}));
		}
	}

	public void prospectMemberConversionMemberStatus(Member member, User user) throws BaseException {
		try {

			// update user role
			User loginuser = member.getLoginUser();
			// remove current role
			dao.deleteMemberRoleByLoginUserId(loginuser.getUserId(), SystemConstant.PROSPECT_MEMBER_ROLE.getRoleId());
			member.setStatus(MemberConstant.MEMBER_STATUS_MEMBER);
			member.setModifiedBy(user);
			member.setModifiedDate(new Date());
			dao.update(member);

			loginuser.setModifiedBy(user);
			loginuser.setModifiedDate(new Date());
			UserRole usrrole = new UserRole();
			usrrole.setUser(loginuser);
			usrrole.setRole(SystemConstant.MEMBER_ROLE);
			usrrole.setCreatedBy(user);
			usrrole.setCreatedDate(new Date());

			dao.update(loginuser);
			dao.update(usrrole);

			// send email
			String subject = "You're Our Member";

			// send action bulletin user

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("", new Object[] {}));
		}
	}

	/*
	 * public void prospectMemberRefundAction(Member member,User user)throws BaseException{ try{ Date today = new
	 * Date(); if(member.getEndCoolingPeriod().before(today)){
	 * 
	 * member.setStatus(MemberConstant.MEMBER_STATUS_REQ_REFUND); member.setModifiedBy(user); member.setModifiedDate(new
	 * Date()); dao.update(member);
	 * 
	 * //notify user req refund ActionBulletin ab = new ActionBulletin(); ab.setActionBean("");
	 * ab.setActionMethod("");//TODO ab.setActionParam1(member.getMemberId());
	 * ab.setCreatedBy(SystemConstant.SYSTEM_USER); ab.setCreatedDate(new Date());
	 * ab.setIsDeleted(CommonConstant.NOT_DELETED); ab.setUser(member.getLoginUser());
	 * ab.setType(CommonConstant.AB_TYPE_USER); ab.setActionCode("");//TODO dao.save(ab);
	 * 
	 * //notify finance user req refund ActionBulletin fab = new ActionBulletin(); fab.setActionBean("");
	 * fab.setActionMethod("");//TODO fab.setActionParam1(member.getMemberId());
	 * fab.setCreatedBy(SystemConstant.SYSTEM_USER); fab.setCreatedDate(new Date());
	 * fab.setIsDeleted(CommonConstant.NOT_DELETED); fab.setType(CommonConstant.AB_TYPE_ROLE);
	 * fab.setRole(SystemConstant.FINANCE_ADMIN_ROLE); fab.setActionCode("");//TODO dao.save(fab);
	 * 
	 * }else{ throw new BaseException(SpringUtils.getMessage("", new Object[]{})); }
	 * 
	 * }catch(Exception ex){ ex.printStackTrace(); throw new BaseException(SpringUtils.getMessage("", new Object[]{})); } }
	 */

	public synchronized String getDocumentNo(String type) throws BaseException {
		String documentNo = "";
		try {
			DocControl docControl = setupService.getDocControlByType(type);
			if (docControl == null)
				throw new BaseException(SpringUtils.getMessage("error.doc.type.not.config", new Object[] { type }));

			StringBuffer numberBuf = new StringBuffer();
			numberBuf.append(docControl.getPrefix());
			long counter = docControl.getNumber() + 1;
			long currentSize = new Long(String.valueOf(counter).length()).longValue();
			long size = docControl.getSize();
			for (long l = currentSize; l < size; l++) {
				numberBuf.append("0");
			}
			numberBuf.append(counter);
			documentNo = numberBuf.toString();
			docControl.setNumber(counter);
			setupService.updateDocControl(docControl);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.generate.doc.no", new Object[] { type }));
		}
		return documentNo;
	}

	public Member getMemberByUserId(String userId) throws BaseException {
		try {
			return dao.getMemberByUserId(userId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member", new Object[] {}));
		}
	}

	public MemberInd getMemberIndByMemberId(String memberId) throws BaseException {
		try {
			return dao.getMemberIndByMemberId(memberId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member", new Object[] {}));
		}
	}

	public List<MemberIndAcct> getMemberIndAcctByMemberInd(String ind) throws BaseException {
		try {
			return dao.getMemberIndAcctListByMemberIndId(ind);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.dependant.list", new Object[] {}));
		}
	}

	public List<MemberIndAcct> getMemberIndAcctByMemberComp(String ind) throws BaseException {
		try {
			return dao.getMemberIndAcctListByMemberCompId(ind);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.nomimee.lis", new Object[] {}));
		}
	}

	public Member getMemberById(String id) throws BaseException {
		try {
			return (Member) dao.getObject(Member.class, id);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member", new Object[] {}));
		}
	}

	// doc master
	public List<DocCheckList> getDocCheckListList() throws BaseException {
		try {
			return dao.getDocCheckList();
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.doc.checklist", new Object[] {}));
		}
	}

	public void createDocCheckList(DocCheckList checklist, User createUser) throws BaseException {
		try {

			List list = dao
					.getDocCheckListCodeTitleType(checklist.getCode(), checklist.getTitle(), checklist.getType());
			if (list.size() > 0) {
				throw new BaseException(SpringUtils.getMessage("error.duplicate.doc.checklist", new Object[] {}));
			}

			checklist.setCreatedBy(createUser);
			checklist.setCreatedDate(new Date());
			checklist.setIsDeleted(CommonConstant.NOT_DELETED);
			dao.save(checklist);

		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		}

		catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.create.doc.checklist", new Object[] {}));
		}
	}

	public void editDocCheckList(DocCheckList checklist, User createUser) throws BaseException {
		try {

			List<DocCheckList> list = dao.getDocCheckListCodeTitleType(checklist.getCode(), checklist.getTitle(),
					checklist.getType());
			if (list.size() > 0) {
				for (DocCheckList doc : list) {
					if (!doc.getDocCheckListId().equalsIgnoreCase(checklist.getDocCheckListId())) {
						throw new BaseException(SpringUtils
								.getMessage("error.duplicate.doc.checklist", new Object[] {}));
					}
				}
			}

			checklist.setModifiedBy(createUser);
			checklist.setModifiedDate(new Date());
			checklist.setIsDeleted(CommonConstant.NOT_DELETED);
			dao.merge(checklist);

		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.edit.doc.checklist", new Object[] {}));
		}
	}

	public void deleteDocCheckList(List<DocCheckList> checklist, User createUser) throws BaseException {
		try {

			for (DocCheckList doc : checklist) {
				if (doc.isMarkAsAction()) {
					doc.setModifiedBy(createUser);
					doc.setModifiedDate(new Date());
					doc.setIsDeleted(CommonConstant.NOT_DELETED);
					dao.update(doc);
				}
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.delete.doc.checklist", new Object[] {}));
		}
	}

	public List<Member> searchRegNoPartnerNameInList(String regno, List<Member> memberList) throws BaseException {

		List<Member> plist = new ArrayList<Member>();

		if (regno == null) {
			regno = "";
		}

		if (regno.length() == 0) {
			return memberList;
		}

		for (Member p : memberList) {
			if (p.getMemberRegNo().equalsIgnoreCase(regno)) {
				plist.add(p);
				continue;
			}
		}

		return plist;

	}

	public List<Member> getProspectMemberList() throws BaseException {
		try {

			List<String> statusList = new ArrayList<String>();
			statusList.add(MemberConstant.MEMBER_STATUS_PENDING_MEMBER);
			statusList.add(MemberConstant.MEMBER_STATUS_PORSPECT_PENDING_ACK_PAYMENT);
			statusList.add(MemberConstant.MEMBER_STATUS_PROSPECT_PENDING_AGREEMENT);
			statusList.add(MemberConstant.MEMBER_STATUS_PROSPECT_ACK_AGREEMENT);
			statusList.add(MemberConstant.MEMBER_STATUS_PROSPECT_PENDING_CHECK_LIST);
			statusList.add(MemberConstant.MEMBER_STATUS_PROSPECT_PENDING_CHECK_LIST);
			List<Member> mList = dao.getMemberListWithStatus(statusList);
//			for (Member member : mList) {
//				Agreement agreement = dao.getAgreementByMemberId(member.getMemberId());
//				member.setAgreement(agreement);
//			}

			return mList;

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.list", new Object[] {}));
		}
	}

	public List<DocSubmission> getMemberDocSubmissionList(String memberId, String type) throws BaseException {
		try {
			return dao.getDocSubmission(memberId, type);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.doc.list", new Object[] {}));
		}
	}

	public void completeCheckMemberDoc(Member member, List<DocSubmission> mandList, List<DocSubmission> notmandList,
			User checkUser) throws BaseException {
		try {

			for (DocSubmission doc : notmandList) {
				doc.setModifiedBy(checkUser);
				doc.setModifiedDate(new Date());
				dao.update(doc);
			}

			for (DocSubmission doc : mandList) {
				doc.setModifiedBy(checkUser);
				doc.setModifiedDate(new Date());
				dao.update(doc);
			}

			member.setStatus(MemberConstant.MEMBER_STATUS_PENDING_MEMBER);
			member.setModifiedBy(checkUser);
			member.setModifiedDate(new Date());
			dao.update(member);

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.check.member.doc.list", new Object[] {}));
		}
	}

	public void checkMemberDoc(Member member, List<DocSubmission> mandList, List<DocSubmission> notmandList,
			User checkUser) throws BaseException {
		try {

			for (DocSubmission doc : notmandList) {
				doc.setModifiedBy(checkUser);
				doc.setModifiedDate(new Date());
				dao.update(doc);
			}

			for (DocSubmission doc : mandList) {
				doc.setModifiedBy(checkUser);
				doc.setModifiedDate(new Date());
				dao.update(doc);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.check.member.doc.list", new Object[] {}));
		}
	}

	public void memberConversion(Member member, User user) throws BaseException {
		try {
			List<Member> lisst = dao.getMemberListByMembershipNo(member.getMembershipNo());
			if (lisst.size() > 0) {
				throw new BaseException("ss");
			}

			// update user role
			User loginuser = member.getLoginUser();
			// remove current role
			log.debug("userId=" + loginuser.getUserId());
			log.debug("roleId=" + SystemConstant.PROSPECT_MEMBER_ROLE.getRoleId());
			dao.deleteMemberRoleByLoginUserId(loginuser.getUserId(), SystemConstant.PROSPECT_MEMBER_ROLE.getRoleId());
			// log.debug("Test here...");
			member.setMembershipNo(generateMembershipNo(member));
			member.setStatus(MemberConstant.MEMBER_STATUS_MEMBER);
			member.setModifiedBy(user);
			member.setModifiedDate(new Date());
			dao.update(member);

			loginuser.setModifiedBy(user);
			loginuser.setModifiedDate(new Date());
			dao.merge(loginuser);

			UserRole usrrole = new UserRole();
			usrrole.setUser(loginuser);
			usrrole.setRole(SystemConstant.MEMBER_ROLE);
			usrrole.setCreatedBy(user);
			usrrole.setCreatedDate(new Date());
			dao.save(usrrole);
			// dao.update(loginuser);
			// dao.update(usrrole);

			/*
			 * member.setStatus(MemberConstant.MEMBER_STATUS_MEMBER); member.setModifiedDate(new Date());
			 * member.setModifiedDate(new Date()); dao.update(member);
			 */

			// calculate commission
			if (member.getRegistrationType().equalsIgnoreCase(MemberConstant.MEMBER_REG_AGENT)) {
				Agent agent = member.getAgent();
				// System.out.println("---calculate commission--agent="+agent);
				// System.out.println("---calculate commission--member.getAgreement()="+member.getAgreement());
				// System.out.println("---calculate commission--agentService="+agentService);
				// Commended by jimmy because commission is not calculated here..should be end of day.
				// agentService.calculateAgreementCommission(member.getAgreement(), agent);

				// throw new BaseException("Testing and debug");
			}
			//

			// generate point
			Agreement agreement = dao.getAgreementByMemberId(member.getMemberId());
			Membership membership = agreement.getMembership();
			List<PointMembershipMap> pointList = dao.getPointMembershipMapList(membership.getMembershipId());
			Calendar calendar = GregorianCalendar.getInstance();
			calendar.setTime(new Date());
			int year = calendar.get(Calendar.YEAR);
			calendar.add(Calendar.YEAR, 1);
			Date expiry = calendar.getTime();
			for (PointMembershipMap map : pointList) {
				MemberPointEntitle entitle = new MemberPointEntitle();
				entitle.setPoint(map.getPoint());
				entitle.setAgreement(agreement);
				entitle.setYear(new Integer(year));
				entitle.setPointCategory(map.getPointCategory());
				entitle.setCreatedBy(SystemConstant.SYSTEM_USER);
				entitle.setCreatedDate(new Date());
				entitle.setStatus(MemberConstant.MEMBER_POINT_VALID);
				entitle.setIsDeleted(CommonConstant.NOT_DELETED);
				entitle.setExpiryDate(expiry);
				dao.save(entitle);
			}
			String newTransactionDesc = SpringUtils.getMessage(MemberConstant.TRANS_NEW_ENTITLEMENT,
					new Object[] { year });
			insertMemberTransaction(agreement.getAgreementId(), newTransactionDesc);

		} catch (BaseException be) {
			throw be;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.conversion.member", new Object[] {}));
		}
	}

	public Agreement getAgreementByMemberId(String memberId) throws BaseException {
		try {
			return dao.getAgreementByMemberId(memberId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.agreement", new Object[] {}));
		}
	}

	public List<Agreement> getActiveAgreementsByAgent(String agentId) throws BaseException {
		try {
			return dao.getActiveAgreementListByAgent(agentId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException("Error on getActiveAgreementByAgent");
		}
	}

	public void saveTerminateAgreement(List<Agreement> agreementsToTerminate, String affectQuota,
			String affectCommission, double refundToMember, User user) throws Exception {

		for (Agreement agreement : agreementsToTerminate) {
			agreement.setAffectQuota(affectQuota);
			agreement.setAffectCommission(affectCommission);
			agreement.setRefundToMember(refundToMember);
			agreement.setModifiedBy(user);
			agreement.setModifiedDate(new Date());
			agreement.setStatus(AgreementConstant.AGREEMENT_STATUS_TERMINATED);
			agreement.setAgreementTerminateDate(new Date());
			dao.update(agreement);

			if (financeService.getValidAgreement(agreement.getMember().getMemberId()).size() < 2) {

				agreement.getMember().setStatus(MemberConstant.MEMBER_STATUS_INACTIVE);
				agreement.getMember().getLoginUser().setStatus(CommonConstant.STATUS_NO);
				agreement.getMember().getLoginUser().setModifiedBy(user);
				agreement.getMember().setModifiedBy(user);
				agreement.getMember().setModifiedDate(new Date());
				dao.update(agreement.getMember().getLoginUser());
				dao.update(agreement.getMember());

			}
		}

	}

	public void savePreTerminateAgreement(List<Agreement> agreements) throws Exception {
		List<Agreement> agreementToTerminate = new ArrayList<Agreement>();
		String agreementsNo = "";
		for (Agreement agreement : agreements) {
			if (agreement.isMarkAsAction()) {
				agreementsNo = agreementsNo + agreement.getAgreetmentNo() + ",";
				agreementToTerminate.add(agreement);
			}
		}
		if (agreementsNo.endsWith(",")) {
			agreementsNo = agreementsNo.substring(0, agreementsNo.length() - 1);
		}
		if (agreementToTerminate.size() == 0) {
			throw new BaseException("Please select atleast one agreement.");
		}

		ActionBulletin ab = new ActionBulletin();
		ab.setActionBean(AdminAgreementTerminateBean.BEAN_NAME);
		ab.setActionMethod(AdminAgreementTerminateBean.NAV_ACTION_BULETIN);
		ab.setActionCode("Agreement Termination for " + agreementsNo + " . Waiting for Approval. ");
		ab.setActionParam1(agreementsNo);
		ab.setActionParam2(agreements.get(0).getMember().getMemberId());
		ab.setCreatedBy(SystemConstant.SYSTEM_USER);
		ab.setCreatedDate(new Date());
		ab.setIsDeleted(CommonConstant.NOT_DELETED);
		ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
		ab.setActionNo(SystemUtil.getUniqueCode());
		systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);

	}

	public List<Agreement> getActiveAgreementsByMember(String memberId) throws BaseException {
		try {
			return dao.getActiveAgreementListByMember(memberId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException("Error on getActiveAgreementsByMember");
		}
	}

	public List<Member> getProspectMemberList(Agent agent) throws BaseException {
		try {

			List<String> statusList = new ArrayList<String>();
			statusList.add(MemberConstant.MEMBER_STATUS_PENDING_MEMBER);
			statusList.add(MemberConstant.MEMBER_STATUS_PORSPECT_PENDING_ACK_PAYMENT);
			statusList.add(MemberConstant.MEMBER_STATUS_PROSPECT_PENDING_AGREEMENT);
			statusList.add(MemberConstant.MEMBER_STATUS_PROSPECT_ACK_AGREEMENT);
			statusList.add(MemberConstant.MEMBER_STATUS_PROSPECT_PENDING_CHECK_LIST);
			statusList.add(MemberConstant.MEMBER_STATUS_PROSPECT_PENDING_CHECK_LIST);
			List<Member> mList = dao.getAgentMemberListWithStatus(statusList, agent.getAgentId());
			for (Member member : mList) {
				Agreement agreement = dao.getAgreementByMemberId(member.getMemberId());
				member.setAgreement(agreement);
			}

			return mList;

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.list", new Object[] {}));
		}
	}

	// Added By Jacky 25-May-2008 1626
	public List<Member> getMemberListByAgent(Agent agent) throws BaseException {
		try {

			List<String> statusList = new ArrayList<String>();
			statusList.add(MemberConstant.MEMBER_STATUS_MEMBER);
			List<Member> mList = dao.getAgentMemberListWithStatus(statusList, agent.getAgentId());
			// added by jimmy because no one member got many agreement. it cause error when not unique return.
			// for(Member member:mList){
			// Agreement agreement = dao.getAgreementByMemberId(member.getMemberId());
			// member.setAgreement(agreement);
			// }

			return mList;

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.list", new Object[] {}));
		}
	}

	// Added By Jacky 28-03-2008 1017
	public List<Member> getMemberActiveList() throws BaseException {
		try {

			List<String> statusList = new ArrayList<String>();
			statusList.add(MemberConstant.MEMBER_STATUS_MEMBER);
			List<Member> mList = dao.getMemberListWithStatus(statusList);

			// comment by jimmy because it cause error. now member can have more than one agreement.
			// for(Member member:mList){
			// Agreement agreement = dao.getAgreementByMemberId(member.getMemberId());
			// member.setAgreement(agreement);
			// }

			return mList;

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.list", new Object[] {}));
		}
	}

	public List<Member> getMemberActiveList(Agent agent) throws BaseException {
		try {

			List<String> statusList = new ArrayList<String>();
			statusList.add(MemberConstant.MEMBER_STATUS_MEMBER);
			List<Member> mList = dao.getMemberListWithStatus(statusList, agent);
			// for(Member member:mList){
			// Agreement agreement = dao.getAgreementByMemberId(member.getMemberId());
			// member.setAgreement(agreement);
			// }

			return mList;

		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.list", new Object[] {}));
		}
	}

	public List<Agreement> getAgreementListByMemberId(String memberId) throws BaseException {
		try {
			return dao.getAgreementListByMemberId(memberId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.agreement.list", new Object[] {}));
		}
	}

	public List<MemberPointEntitle> getMemberPointEntitleList(String agreementId) throws BaseException {
		try {
			return dao.getMemberPointEntitleList(agreementId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.agreement.point.list", new Object[] {}));
		}
	}

	public List<MemberPointEntitle> getMemberPointEntitleList(String agreementId, String pointCatId)
			throws BaseException {
		try {
			return dao.getMemberPointEntitleList(agreementId, pointCatId);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.get.member.agreement.point.list", new Object[] {}));
		}
	}

	public void updateMemberIndProfileAction(Member member, MemberInd memberind, List<MemberIndAcct> dList, User user)
			throws BaseException {
		try {

			member.setModifiedBy(user);
			member.setModifiedDate(new Date());
			dao.update(member);
			memberind.setModifiedBy(user);
			memberind.setModifiedDate(new Date());
			dao.update(memberind);

			for (MemberIndAcct m : dList) {
				m.setModifiedBy(user);
				m.setModifiedDate(new Date());
				dao.update(m);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.update.member.profile", new Object[] {}));
		}
	}

	public void updateMemberCompProfileAction(Member member, MemberComp memberComp, List<MemberIndAcct> dList, User user)
			throws BaseException {
		try {

			member.setModifiedBy(user);
			member.setModifiedDate(new Date());
			dao.update(member);
			memberComp.setModifiedBy(user);
			memberComp.setModifiedDate(new Date());
			dao.update(memberComp);

			for (MemberIndAcct m : dList) {
				m.setModifiedBy(user);
				m.setModifiedDate(new Date());
				dao.update(m);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.update.member.profile", new Object[] {}));
		}
	}

	private synchronized void generatePaymentInstallmentInvoice(InstallmentSchema schema, Agreement agreement,
			Finance finance, User refUser) throws Exception {
		double fee = agreement.getMembership().getMembershipFeeDbl()
				- (agreement.getMembership().getMembershipFeeDbl() * schema.getDepositPercentDbl()) / 100;

		double monthPay = fee / schema.getMonthInt();
		monthPay = (Math.round(monthPay * 100.0)) / 100.0;

		int month = schema.getMonthInt();
		Calendar calendar = GregorianCalendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		for (int i = 1; i < month; i++) {
			calendar.add(Calendar.MONTH, 1);
			String newInvoiceNo = financeService.getDocumentNo(CommonConstant.DOC_TYPE_INVOICE);
			Invoice invoice = new Invoice();
			invoice.setCreatedBy(SystemConstant.SYSTEM_USER);
			invoice.setCreatedDate(new Date());
			invoice.setInvoiceAmount(monthPay);
			invoice.setInvoiceDate(calendar.getTime());
			invoice.setInvoiceNo(newInvoiceNo);
			invoice.setIsDeleted(CommonConstant.NOT_DELETED);
			invoice.setRefId(agreement.getAgreementId());
			invoice.setFinance(finance);
			invoice.setRefUser(refUser);
			dao.save(invoice);

			// generate invoice dtl
			InvoiceDtl invoiceDtl = new InvoiceDtl();
			invoiceDtl.setInvoice(invoice);
			invoiceDtl.setCreatedBy(SystemConstant.SYSTEM_USER);
			invoiceDtl.setCreatedDate(new Date());
			invoiceDtl.setIsDeleted(CommonConstant.NOT_DELETED);
			invoiceDtl.setItemAmount(invoice.getInvoiceAmount());
			invoiceDtl.setItemType(CommonConstant.INVOICE_TYPE_INSTALLMENT);
			invoiceDtl.setStatus(CommonConstant.INVOICE_STATUS_ACTIVE);
			invoiceDtl.setItemDesc(CommonConstant.INVOICE_INSTALLMENT_ITEM_DESC + i);
			dao.save(invoiceDtl);
		}

	}

	private synchronized void generateDownPaymentInstallmentInvoice(InstallmentSchema ischema,
			DownPaymentInstallmentSchema schema, Agreement agreement, Finance finance, User refUser) throws Exception {

		double fee = (agreement.getMembership().getMembershipFeeDbl() * (ischema.getDepositPercentDbl() / 100));
		int month = schema.getMonthInt();
		double monthPay = fee / schema.getMonthInt();
		monthPay = (Math.round(monthPay * 100.0)) / 100.0;

		Calendar calendar = GregorianCalendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		for (int i = 1; i < month; i++) {
			calendar.add(Calendar.MONTH, 1);
			String newInvoiceNo = financeService.getDocumentNo(CommonConstant.DOC_TYPE_INVOICE);
			Invoice invoice = new Invoice();
			invoice.setCreatedBy(SystemConstant.SYSTEM_USER);
			invoice.setCreatedDate(new Date());
			invoice.setInvoiceAmount(monthPay);
			invoice.setInvoiceDate(calendar.getTime());
			invoice.setInvoiceNo(newInvoiceNo);
			invoice.setIsDeleted(CommonConstant.NOT_DELETED);
			invoice.setRefId(agreement.getAgreementId());
			invoice.setFinance(finance);
			invoice.setRefUser(refUser);
			dao.save(invoice);

			// generate invoice dtl
			InvoiceDtl invoiceDtl = new InvoiceDtl();
			invoiceDtl.setInvoice(invoice);
			invoiceDtl.setCreatedBy(SystemConstant.SYSTEM_USER);
			invoiceDtl.setCreatedDate(new Date());
			invoiceDtl.setIsDeleted(CommonConstant.NOT_DELETED);
			invoiceDtl.setItemAmount(invoice.getInvoiceAmount());
			invoiceDtl.setItemType(CommonConstant.INVOICE_TYPE_DEPOSIT_INSTALLMENT);
			invoiceDtl.setStatus(CommonConstant.INVOICE_STATUS_ACTIVE);
			invoiceDtl.setItemDesc(CommonConstant.INVOICE_DEPOSIT_INSTALLMENT_ITEM_DESC + i);
			dao.save(invoiceDtl);
		}

	}

	public List<InvoiceDtl> getInvoiceDtlByAgreementId(String id) throws BaseException {
		try {
			return dao.getInvoiceDtlListByAgreementId(id);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.agreement.invoice", new Object[] {}));
		}
	}

	public List<Invoice> getInvoiceByAgreementId(String id) throws BaseException {
		try {
			List<Invoice> list = dao.getInvoiceByAgreementId(id);
			for (Invoice invoice : list) {
				InvoiceDtl dtl = dao.getInvoiceDtlByInvoiceId(invoice.getInvoiceId());
				invoice.setInvoiceDtl(dtl);
			}

			return list;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.agreement.invoice", new Object[] {}));
		}
	}

	// Added by Jacky 17-Nov-2008 1820----------
	public String generatePreMembershipNo(Member member) throws BaseException {
		String membershipNo = "";
		try {
			membershipNo = adminService.getPreDocumentNo(CommonConstant.DOC_TYPE_MEMBERSHIP_NO);
			if (member.getMemberType().equalsIgnoreCase(CommonConstant.MEMBER_TYPE_COMP))
				membershipNo = membershipNo.concat("/C");
			else
				membershipNo = membershipNo.concat("/I");
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "generatePreMembershipNo" }));
		}
		return membershipNo;
	}

	private String generateMembershipNo(Member member) throws BaseException {
		String membershipNo = "";
		try {
			membershipNo = adminService.getDocumentNo(CommonConstant.DOC_TYPE_MEMBERSHIP_NO);
			if (member.getMemberType().equalsIgnoreCase(CommonConstant.MEMBER_TYPE_COMP))
				membershipNo = membershipNo.concat("/C");
			else
				membershipNo = membershipNo.concat("/I");
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "generatePreMembershipNo" }));
		}
		return membershipNo;
	}

	public List<MemberTransaction> getMemberTransactionList(String agreementId) throws BaseException {
		List<MemberTransaction> list = new ArrayList<MemberTransaction>();
		try {
			List<MemberTransaction> pList = dao.getMemberTransactionList(agreementId);
			for (MemberTransaction m : pList) {
				List<MemberTransactionEntitlement> transEntitlelist = dao.getMemberTransactionEntitlementList(m
						.getMemberTransactionId());
				m.setMemberTransactionEntitlementList(transEntitlelist);
				list.add(m);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[] { MemberTransaction.class
					.getSimpleName() }));
		}
		return list;
	}

	/**
	 * replicated in financeservice
	 */
	public void insertMemberTransaction(String agreementId, String transactionDesc) throws BaseException {
		try {
			MemberTransaction mt = new MemberTransaction();
			Agreement a = (Agreement) dao.getObject(Agreement.class, agreementId);
			mt.setAgreement(a);
			mt.setCreatedDate(new Date());
			mt.setIsDeleted(CommonConstant.NOT_DELETED);
			mt.setTransactionDate(new Date());
			mt.setTransactionDesc(transactionDesc);

			dao.save(mt);

			List<MemberPointEntitle> currentPointList = dao.getMemberPointEntitleActiveList(agreementId);

			for (MemberPointEntitle mpe : currentPointList) {
				MemberTransactionEntitlement mte = new MemberTransactionEntitlement();
				mte.setMemberTransaction(mt);
				mte.setCreatedDate(new Date());
				mte.setIsDeleted(CommonConstant.NOT_DELETED);
				mte.setPointBalance(mpe.getPoint());
				mte.setPointCategory(mpe.getPointCategory());
				mte.setReservedPoint(mpe.getReservedPoint());
				mte.setYear(mpe.getYear());
				mte.setExpiryDate(mpe.getExpiryDate());
				dao.save(mte);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "insertMemberTransaction" }));
		}
	}

	// added by jimmy for booking

	public void insertMemberTransaction(String agreementNo, Integer year, String newBookingTransactionDesc)
			throws BaseException {
		try {
			MemberTransaction mt = new MemberTransaction();
			Agreement a = (Agreement) dao.getAgreementByAgreeNo(agreementNo);
			mt.setAgreement(a);
			mt.setCreatedDate(new Date());
			mt.setIsDeleted(CommonConstant.NOT_DELETED);
			mt.setTransactionDate(new Date());
			mt.setTransactionDesc(newBookingTransactionDesc);

			dao.save(mt);

			List<MemberPointEntitle> lists;
			try {
				lists = dao.getValidMemberPointEntitleList(agreementNo, year);
			} catch (Exception e) {
				e.printStackTrace();
				throw new BaseException(SpringUtils.getMessage("error.invoke.method",
						new Object[] { "insertMemberTransaction" }));
			}

			for (MemberPointEntitle mpe : lists) {
				MemberTransactionEntitlement mte = new MemberTransactionEntitlement();
				mte.setMemberTransaction(mt);
				mte.setCreatedDate(new Date());
				mte.setIsDeleted(CommonConstant.NOT_DELETED);
				mte.setPointBalance(mpe.getPoint());
				mte.setPointCategory(mpe.getPointCategory());
				mte.setReservedPoint(mpe.getReservedPoint());
				mte.setYear(mpe.getYear());
				mte.setExpiryDate(mpe.getExpiryDate());
				dao.save(mte);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "insertMemberTransaction" }));
		}
	}

	/*
	 * public Payment createProspectIndividualMember(Member member,MemberInd memberInd,List<MemberIndAcct> list, User
	 * createdUser,Payment payment,PaymentDtl paytmentDtl,StandingInstruction instruction ,Agreement agreement,double
	 * actualPayment)throws BaseException{ try{
	 * 
	 * }catch(BaseException) } public Payment createProspectCompMember(Member member,MemberComp memberComp, User
	 * createdUser, List<MemberIndAcct> list, Payment payment,PaymentDtl paytmentDtl,StandingInstruction instruction
	 * ,Agreement agreement,double actualPayment)throws BaseException;
	 */

	// added by jimmy for booking
	public void saveAgreenmentTransfer(Member member, Agreement agreement, MemberComp memberComp, double invoiceCharge,
			String remark) throws Exception {

		try {
			// validate by comp name
			List<MemberComp> clist = dao.getMemberCompByCompName(memberComp.getCompName().trim());
			if (clist != null && clist.size() > 0) {
				throw new BaseException(SpringUtils.getMessage("error.duplicate.corporate.member", new Object[] {}));
			}

			member.setCreatedDate(new Date());
			member.setIsDeleted(CommonConstant.NOT_DELETED);
			member.setMemberType(CommonConstant.MEMBER_TYPE_COMP);
			member.setStatus(MemberConstant.MEMBER_STATUS_PORSPECT_PENDING_ACK_PAYMENT);
			// member.setPaymentStatus(MemberConstant.MEMBER_PAYMENT_STATUS_PENDING_ACK_DEPOSIT);
			member.setEmail(memberComp.getEmail());

			String no = getDocumentNo(CommonConstant.DOC_TYPE_PROSPECT_REG);
			member.setMemberRegNo(no);

			User user = adminService.createNewUserWithRole(member.getEmail(), SystemConstant.DEFAULT_PASSWORD,
					SystemConstant.PROSPECT_MEMBER_ROLE, SystemConstant.SYSTEM_USER);
			member.setLoginUser(user);
			member.setMembershipNo(generateMembershipNo(member));
			// member.setIcno(memberComp.getCompName());
			dao.save(member);

			memberComp.setCreatedBy(member.getCreatedBy());
			memberComp.setCreatedDate(new Date());
			memberComp.setIsDeleted(CommonConstant.NOT_DELETED);
			memberComp.setMember(member);
			dao.save(memberComp);

			agreement.setModifiedBy(member.getCreatedBy());
			agreement.setModifiedDate(new Date());
			agreement.setNewMember(member);
			dao.update(agreement);

			saveTransferCharge(member, agreement, invoiceCharge);

			// send email notification
			/*
			 * emailManager.sendEmail("You're have successfully become a Prospect Member.\n " + "This is your temporary
			 * login username & password:\n" + "Username:"+memberComp.getCompName().trim()+"\n" +
			 * "Password:"+SystemConstant.DEFAULT_PASSWORD+"\n" , memberComp.getEmail(), "Registration Succesfully",
			 * SystemConstant.SYSTEM_EMAIL);
			 */

			// create action bulletin for finance module
			/*
			 * List<User> usrList = adminDao.getUserByRole(SystemConstant.FINANCE_ADMIN_ROLE.getRoleId()); // for(User
			 * usr:usrList){
			 */
			// ActionBulletin ab = new ActionBulletin();
			// ab.setActionBean(MemberPaymentBean.BEAN_NAME);
			// ab.setActionMethod("viewMemberPayment");
			// ab.setActionParam1(payment.getPaymentId());
			// ab.setActionNo(SystemUtil.getUniqueCode());
			// ab.setActionNav(MemberPaymentBean.NAV_VIEW_MEMBER_PAYMENT);
			// ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			// ab.setCreatedDate(new Date());
			// ab.setIsDeleted(CommonConstant.NOT_DELETED);
			// ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			// ab.setActionCode(SpringUtils.getMessage(ActionBulletinConstant.VIEW_MEMBER_PAYMENT_ACTION_CODE, new
			// Object[]{payment.getReceiptNo()}));
			// systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);
			// }
			String name = "";
			if (agreement.getMember().getMemberType().equalsIgnoreCase(CommonConstant.MEMBER_TYPE_COMP)) {
				MemberComp memberComp2 = dao.getMemberCompByMemberId(member.getMemberId());
				name = memberComp2.getCompName();
			} else {
				MemberInd memberInd2 = dao.getMemberIndByMemberId(member.getMemberId());
				name = memberInd2.getNameAsIcPassport();
			}

			ActionBulletin ab = new ActionBulletin();
			ab.setActionBean(MemberAgreementTransferBean.BEAN_NAME);
			ab.setActionMethod(MemberAgreementTransferBean.NAV_ACTION_BULETIN);
			ab.setActionCode("Member " + (name == null ? "" : name) + " Agreement Transfer. Invoice Charge RM"
					+ invoiceCharge);
			ab.setActionParam1(agreement.getAgreementId());
			ab.setActionParam2(agreement.getMember().getMembershipNo());
			ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			ab.setCreatedDate(new Date());
			ab.setIsDeleted(CommonConstant.NOT_DELETED);
			ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			ab.setActionNo(SystemUtil.getUniqueCode());
			systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);
		} catch (BaseException ex) {
			ex.printStackTrace();
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.create.corporate.member", new Object[] {}));
		}

	}

	public void saveTransferCharge(Member member, Agreement agreement, double invoiceCharge) throws Exception {
		if (invoiceCharge == 0) {
			throw new BaseException("Invoice Charge can not be 0.");
		}
		Finance finance = new Finance();
		finance.setCreatedBy(member.getCreatedBy());
		finance.setCreatedDate(new Date());
		finance.setIsDeleted(CommonConstant.NOT_DELETED);
		finance.setAgreement(agreement);
		dao.save(finance);

		String newInvoiceNo = financeService.getDocumentNo(CommonConstant.DOC_TYPE_INVOICE);
		// Payment payment = new Payment();
		// payment.setFinance(finance);
		// payment.setPaymentDate(new Date());
		// payment.setRefId(agreement.getAgreementId());
		// payment.setCreatedBy(member.getCreatedBy());
		// payment.setCreatedDate(new Date());
		// payment.setPaymentDate(new Date());
		// payment.setPaymentAmount(invoiceCharge);
		// payment.setReceiptNo(financeService.getDocumentNo(CommonConstant.DOC_TYPE_RECEIPT));
		// payment.setIsDeleted(CommonConstant.NOT_DELETED);
		// payment.setStatus(PaymentConstant.PAYMENT_STATUS_PENDING);
		// dao.save(payment);
		//		
		// PaymentDtl paymentDtl = new PaymentDtl();
		// paymentDtl.setPayment(payment);
		// //paymentDtl.setInvoiceDtl(invoiceDtl);
		// paymentDtl.setCreatedBy(member.getCreatedBy());
		// paymentDtl.setCreatedDate(new Date());
		// paymentDtl.setIsDeleted(CommonConstant.NOT_DELETED);
		// paymentDtl.setAmount(invoiceCharge);
		// dao.save(paymentDtl);

		// generate invoice
		Invoice invoice = new Invoice();
		invoice.setCreatedBy(member.getCreatedBy());
		invoice.setCreatedDate(new Date());
		invoice.setInvoiceAmount(invoiceCharge);
		invoice.setInvoiceDate(new Date());
		invoice.setInvoiceNo(newInvoiceNo);
		invoice.setIsDeleted(CommonConstant.NOT_DELETED);
		invoice.setRefId(agreement.getAgreementId());
		invoice.setFinance(finance);
		// invoice.setPayment(payment); TODO why got invoice.payment. invoice should have many invoice. why?
		dao.save(invoice);

		// generate invoice dtl
		InvoiceDtl invoiceDtl = new InvoiceDtl();
		invoiceDtl.setInvoice(invoice);
		invoiceDtl.setCreatedBy(member.getCreatedBy());
		invoiceDtl.setCreatedDate(new Date());
		invoiceDtl.setIsDeleted(CommonConstant.NOT_DELETED);
		invoiceDtl.setItemAmount(invoice.getInvoiceAmount());
		invoiceDtl.setItemType(CommonConstant.INVOICE_TYPE_AGREEMENT_TRANSFER);
		invoiceDtl.setStatus(CommonConstant.INVOICE_STATUS_ACTIVE);
		invoiceDtl.setItemDesc(CommonConstant.INVOICE_DEPOSIT_AGREEMENT_TRAN_DESC);
		invoiceDtl.setPaidAmount(0d);
		dao.save(invoiceDtl);

	}

	public static Double getNewTotalPaymentPrice(Agreement agreement, Membership toMembership, Double paid)
			throws Exception {

		double interestPaid = agreement.getMemberScheduleScheme().getInstalledMonth()
				* agreement.getMemberScheduleScheme().getInterestRate()
				* agreement.getMemberScheduleScheme().getTotalPrice();

		double total = toMembership.getMembershipFee() + interestPaid;
		double totalAfterPay = total - paid;

		return totalAfterPay;
	}

	public void saveChangeMembership(Agreement agreement, Membership toMembership, String remark, User user,
			Double totalAfterPay) throws Exception {
		if (totalAfterPay == null) {
			Double paid = financeDao.getTotalPaidInstallment(agreement.getAgreementId());
			totalAfterPay = getNewTotalPaymentPrice(agreement, toMembership, paid);
		}
		agreement.setMembership(toMembership);
		agreement.setFullMembershipPrice(toMembership.getMembershipFee());
		agreement.setModifiedBy(user);
		agreement.setModifiedDate(new Date());
		dao.update(agreement);
		agreement.getMemberScheduleScheme().setTotalPrice(totalAfterPay);
		agreement.getMemberScheduleScheme().setModifiedBy(user);
		agreement.getMemberScheduleScheme().setModifiedDate(new Date());
		agreement.getMemberScheduleScheme().setInterestRate(agreement.getInstallmentSchema().getInterestRate());
		agreement.setMembershipChangeLog(null);
		dao.update(agreement.getMemberScheduleScheme());
	}

	public List<InstallmentSchema> getInstallmentSchema() throws Exception {
		return dao.getInstallmentSchema();
	}

	public void savePreChangeMembership(Agreement agreement, Membership toMembership, String remark, User user)
			throws Exception {

		String upgradeDowngrade = "";
		// /validation
		if (agreement.getMembership().getRank().intValue() == toMembership.getRank().intValue()) {
			// same rank
			throw new BaseException("Can not change to same rank of membership.");
		}

		if (agreement.getMemberScheduleScheme().getInstalledMonth() + agreement.getInstallmentSchema().getMonth() > agreement
				.getMembership().getMembershipCategory().getMaxInstallmentMonth()) {
			throw new BaseException("New installment month (" + agreement.getMemberScheduleScheme().getInstalledMonth()
					+ agreement.getInstallmentSchema().getMonth() + ")more than maximum installment month( "
					+ agreement.getMembership().getMembershipCategory().getMaxInstallmentMonth() + ").");
		}
		Double paid = financeDao.getTotalPaidInstallment(agreement.getAgreementId());

		double totalAfterPay = getNewTotalPaymentPrice(agreement, toMembership, paid);
		double interestPaid = agreement.getMemberScheduleScheme().getInstalledMonth()
				* agreement.getMemberScheduleScheme().getInterestRate()
				* agreement.getMemberScheduleScheme().getTotalPrice();
		double paidWithoutInterest = paid - interestPaid;

		// ///////////

		MembershipChangeLog membershipChangeLog = new MembershipChangeLog();
		membershipChangeLog.setApprovedDate(new Date());

		// check upgrade or downgrade. with validate rank.
		if (agreement.getMembership().getRank() > toMembership.getRank()) {
			// downgrade saleadmin
			if (!com.j6.framework.util.DateUtil.isBetweenDateTime(new Date(), agreement.getStartCoolingPeriod(),
					agreement.getEndCoolingPeriod())) {
				throw new BaseException("Agreement is not within cooling off period.");
			}

			upgradeDowngrade = "Downgrade";

			// get outstanding
			// List<InvoiceDtl> invoiceDtls = dao.getInvoiceDtlListByAgreementId(agreement.getAgreementId());
			// InvoiceDtl invoiceDtlDeposit = null;
			// for(InvoiceDtl invoiceDtl : invoiceDtls){
			// // TODO how if it is full payment
			// if (invoiceDtl.getItemType().equalsIgnoreCase(CommonConstant.INVOICE_TYPE_DEPOSIT_INSTALLMENT )){
			// invoiceDtlDeposit = invoiceDtl;
			// }
			// }

			// double installmentPrice = totalAfterPay * agreement.getInstallmentSchema().getInterestRate()/
			// (agreement.getInstallmentSchema().getMonth());
			if (totalAfterPay < 0) {
				// send buletin finance, return money to customer
				ActionBulletin ab = new ActionBulletin();
				ab.setActionCode(upgradeDowngrade + " agreement " + agreement.getAgreementId() + ". Payment amount RM"
						+ totalAfterPay + " is extra payment.");
				ab.setActionParam1(upgradeDowngrade);
				ab.setActionParam2(agreement.getMember().getMembershipNo());
				ab.setCreatedBy(SystemConstant.SYSTEM_USER);
				ab.setCreatedDate(new Date());
				ab.setIsDeleted(CommonConstant.NOT_DELETED);
				ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
				ab.setActionNo(SystemUtil.getUniqueCode());
				ab.setUser(user);
				systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);

			}
			// else{
			// if (agreement.getInstallmentSchema().getInterestRate()!=null &&
			// agreement.getInstallmentSchema().getInterestRate()>0){
			//					 
			// saveChangeMembership( agreement, toMembership , remark, user, totalAfterPay) ;
			//						
			// }
			// }
			saveChangeMembership(agreement, toMembership, remark, user, totalAfterPay);
			// outstanding = toMembership.getMembershipFee()- invoiceDtlDeposit.getPaidAmount();

			// toMembership.getMembershipTerm()

			// finance charges

			// List<MemberPointEntitle> memberPointEntitles = getMemberPointEntitleList(agreement.getAgreementId());
			// List<PointMembershipMap> pointMembershipMaps =
			// dao.getPointMembershipMapList(toMembership.getMembershipId());
			// for(PointMembershipMap map : pointMembershipMaps){
			// for(MemberPointEntitle entitle : memberPointEntitles){
			// if (map.getPointCategory().getCode().equalsIgnoreCase(entitle.getPointCategory().getCode())){
			// entitle.setPoint(map.getPoint());
			// }
			// }
			// }

			// if (){
			//				
			// }
		} else if (agreement.getMembership().getRank() < toMembership.getRank()) {
			// upgrade ms
			upgradeDowngrade = "upgrade";
			if (paidWithoutInterest < ((agreement.getInstallmentSchema().getDepositPercent() / 100) * totalAfterPay)) {
				NumberFormat formatter = new DecimalFormat("#,###,###,##0.00");

				// throw new BaseException ("Your paid amount RM"+paidWithoutInterest + "" +
				// " is lower than "+(agreement.getInstallmentSchema().getDepositPercent()*100)+"% deposit which is
				// RM"+agreement.getInstallmentSchema().getDepositPercent()*totalAfterPay);
				double membershipDeposit = ((agreement.getInstallmentSchema().getDepositPercent() / 100) * totalAfterPay)
						- paidWithoutInterest;
				String msg = "Membership Deposit RM" + formatter.format(membershipDeposit) + ". Member paid amount RM"
						+ paidWithoutInterest + "" + " is lower than "
						+ (agreement.getInstallmentSchema().getDepositPercent()) + "% deposit which is RM"
						+ (agreement.getInstallmentSchema().getDepositPercent() / 100) * totalAfterPay;

				ActionBulletin ab = new ActionBulletin();
				ab.setActionCode(msg);
				ab.setActionBean(MemberAgreementTransferBean.BEAN_NAME);
				ab.setActionMethod(MemberAgreementTransferBean.NAV_ACTION_BULETIN);
				ab.setActionParam1(agreement.getAgreementId());
				ab.setActionParam2(agreement.getMember().getMembershipNo());
				ab.setCreatedBy(user);
				ab.setCreatedDate(new Date());
				ab.setIsDeleted(CommonConstant.NOT_DELETED);
				ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
				ab.setActionNo(SystemUtil.getUniqueCode());
				ab.setUser(user);
				systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);
				membershipChangeLog.setActionNo(ab.getActionNo());

				Finance finance = new Finance();
				finance.setCreatedBy(user);
				finance.setCreatedDate(new Date());
				finance.setIsDeleted(CommonConstant.NOT_DELETED);
				finance.setAgreement(agreement);
				dao.save(finance);

				String newInvoiceNo = financeService.getDocumentNo(CommonConstant.DOC_TYPE_INVOICE);

				// generate invoice
				Invoice invoice = new Invoice();
				invoice.setCreatedBy(user);
				invoice.setCreatedDate(new Date());
				invoice.setInvoiceAmount(membershipDeposit);
				invoice.setInvoiceDate(new Date());
				invoice.setInvoiceNo(newInvoiceNo);
				invoice.setIsDeleted(CommonConstant.NOT_DELETED);
				invoice.setRefId(agreement.getAgreementId());
				invoice.setFinance(finance);
				// invoice.setPayment(payment); TODO why got invoice.payment. invoice should have many invoice. why?
				dao.save(invoice);

				// generate invoice dtl
				InvoiceDtl invoiceDtl = new InvoiceDtl();
				invoiceDtl.setInvoice(invoice);
				invoiceDtl.setCreatedBy(user);
				invoiceDtl.setCreatedDate(new Date());
				invoiceDtl.setIsDeleted(CommonConstant.NOT_DELETED);
				invoiceDtl.setItemAmount(invoice.getInvoiceAmount());
				invoiceDtl.setItemType(CommonConstant.INVOICE_TYPE_DEPOSIT_MEMBERSHIP);
				invoiceDtl.setStatus(CommonConstant.INVOICE_STATUS_ACTIVE);
				invoiceDtl.setItemDesc(CommonConstant.INVOICE_DEPOSIT_MEMBERSHIP_DESC);
				invoiceDtl.setPaidAmount(0d);
				dao.save(invoiceDtl);
				membershipChangeLog.setApprovedDate(null);

				agreement.setMembershipChangeLog(membershipChangeLog);
				
//			 	change to new membership in finance there. when receive payment
			} else {
				agreement.setMembership(membershipChangeLog.getToMembership());
				upgradeMemberPointEntitlement(  agreement,   membershipChangeLog.getFromMembership(), user);
				
			}
		}

		membershipChangeLog.setAgreement(agreement);
		membershipChangeLog.setByUser(user);
		membershipChangeLog.setRemark(remark);
		membershipChangeLog.setTranDate(new Date());
		membershipChangeLog.setFromMembership(agreement.getMembership());
		membershipChangeLog.setToMembership(toMembership);
		dao.save(membershipChangeLog);

		dao.update(agreement);

		insertMemberTransaction(agreement.getAgreementId(), "Request for Membership of agreement "
				+ agreement.getAgreetmentNo() + " change from " + agreement.getMembership().getName() + " to "
				+ toMembership.getName() + ". " + remark);

		// //

	}
 
	/**
	 * replicated in financeservice
	 * @param agreement
	 *            new/toMembership inside agreement.getMember()
	 * @param OldMembership
	 * @throws Exception 
	 */
	public void upgradeMemberPointEntitlement(Agreement agreement, Membership oldMembership , User user) throws Exception{
// if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWePointCate().getCode())){
			
		String transMsg = "Upgrade membership "+ oldMembership.getMembershipCategory().getCode() + " to " + 
			agreement.getMembership().getMembershipCategory().getCode();
		
		
		Calendar c = com.j6.framework.util.DateUtil.setTime(new Date());
		int year = c.get(Calendar.YEAR);
		List<MemberPointEntitle> memberPointEntitles = dao.getValidMemberPointEntitleList(agreement.getAgreetmentNo(),year);
		
		List<PointMembershipMap> pointListNew = dao.getPointMembershipMapList(agreement.getMembership().getMembershipId());
		List<PointMembershipMap> pointListOld = dao.getPointMembershipMapList(oldMembership.getMembershipId());
		  
		for(PointMembershipMap newPointMembershipMap:pointListNew){
		 
			for(PointMembershipMap oldPointMembershipMap:pointListOld){
				if (oldPointMembershipMap.getPointCategory().getCode().equalsIgnoreCase(newPointMembershipMap.getPointCategory().getCode())){
					
					for(MemberPointEntitle entitle : memberPointEntitles){
						if (entitle.getPointCategory().getCode().equalsIgnoreCase(newPointMembershipMap.getPointCategory().getCode())){
							transMsg = transMsg + ". "+entitle.getPointCategory().getCode() + " from " + entitle.getPoint() +" to ";
							// TODO Low priority. How if upgrade point is less than previous.
								entitle.setPoint(entitle.getPoint()+(newPointMembershipMap.getPoint()-oldPointMembershipMap.getPoint()));
								transMsg = transMsg+  entitle.getPoint();
								entitle.setModifiedBy(user);
								entitle.setModifiedDate(new Date());
								dao.update(entitle);
						}
					}
				}
			}
 
		} 
		 
		insertMemberTransaction(agreement.getAgreementId(), transMsg);
	 
	}

	public void saveConfirmTransferAgreement(Agreement agreement, Member member) throws Exception {
		// inactive member if only one agreement.

	}

	public void saveAgreenmentTransfer(Member member, Agreement agreement, MemberInd memberInd, double invoiceCharge,
			String remark) throws Exception {
		// TODO Auto-generated method stub

		// validate by ic-no
		List<MemberInd> clist = dao.getMemberIndByIcNo(memberInd.getNewIcNo());
		if (clist != null && clist.size() > 0) {
			throw new BaseException(SpringUtils.getMessage("error.duplicate.individual.member", new Object[] {}));
		}

		member.setCreatedDate(new Date());
		member.setIsDeleted(CommonConstant.NOT_DELETED);
		member.setMemberType(CommonConstant.MEMBER_TYPE_IND);
		member.setStatus(MemberConstant.MEMBER_STATUS_PORSPECT_PENDING_ACK_PAYMENT);
		// member.setPaymentStatus(MemberConstant.MEMBER_PAYMENT_STATUS_PENDING_ACK_DEPOSIT);
		member.setEmail(memberInd.getEmail());
		String no = getDocumentNo(CommonConstant.DOC_TYPE_PROSPECT_REG);
		member.setMemberRegNo(no);

		User user = adminService.createNewUserWithRole(member.getEmail(), SystemConstant.DEFAULT_PASSWORD,
				SystemConstant.PROSPECT_MEMBER_ROLE, SystemConstant.SYSTEM_USER);
		dao.save(user);

		member.setLoginUser(user);
		member.setMembershipNo(generateMembershipNo(member));
		// member.setIcno(memberInd.getNewIcNo());
		dao.save(member);

		memberInd.setCreatedBy(member.getCreatedBy());
		memberInd.setCreatedDate(new Date());
		memberInd.setIsDeleted(CommonConstant.NOT_DELETED);
		memberInd.setMember(member);
		dao.save(memberInd);

		// for(MemberIndAcct acct:list){
		// acct.setCreatedBy(createdUser);
		// acct.setCreatedDate(new Date());
		// acct.setIsDeleted(CommonConstant.NOT_DELETED);
		// acct.setMemberInd(memberInd);
		// dao.save(acct);
		// }

		saveTransferCharge(member, agreement, invoiceCharge);

		agreement.setModifiedBy(member.getCreatedBy());
		agreement.setModifiedDate(new Date());
		agreement.setNewMember(member);
		dao.update(agreement);
		String name = "";
		if (agreement.getMember().getMemberType().equalsIgnoreCase(CommonConstant.MEMBER_TYPE_COMP)) {
			MemberComp memberComp = dao.getMemberCompByMemberId(member.getMemberId());
			name = memberComp.getCompName();
		} else {
			MemberInd memberInd2 = dao.getMemberIndByMemberId(member.getMemberId());
			name = memberInd2.getNameAsIcPassport();
		}

		ActionBulletin ab = new ActionBulletin();
		ab.setActionBean(MemberAgreementTransferBean.BEAN_NAME);
		ab.setActionMethod(MemberAgreementTransferBean.NAV_ACTION_BULETIN);
		ab.setActionCode("Member " + (name == null ? "" : name) + " Agreement Transfer. Invoice Charge RM"
				+ invoiceCharge);
		ab.setActionParam1(agreement.getAgreementId());
		ab.setActionParam2(agreement.getMember().getMembershipNo());
		ab.setCreatedBy(SystemConstant.SYSTEM_USER);
		ab.setCreatedDate(new Date());
		ab.setIsDeleted(CommonConstant.NOT_DELETED);
		ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
		ab.setActionNo(SystemUtil.getUniqueCode());
		systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);

		// ActionBulletin ab = new ActionBulletin();
		// ab.setActionBean(MemberPaymentBean.BEAN_NAME);
		// ab.setActionMethod("viewMemberPayment");
		// ab.setActionParam1(payment.getPaymentId());
		// ab.setActionNo(SystemUtil.getUniqueCode());
		// ab.setActionNav(MemberPaymentBean.NAV_VIEW_MEMBER_PAYMENT);
		// ab.setCreatedBy(SystemConstant.SYSTEM_USER);
		// ab.setCreatedDate(new Date());
		// ab.setIsDeleted(CommonConstant.NOT_DELETED);
		// ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
		// ab.setActionCode(SpringUtils.getMessage(ActionBulletinConstant.VIEW_MEMBER_PAYMENT_ACTION_CODE, new
		// Object[]{payment.getReceiptNo()}));
		// systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);
		// send email notification
		/*
		 * emailManager.sendEmail("You're have successfully become a Prospect Member.\n " + "This is your temporary
		 * login username & password:\n" + "Username:"+memberInd.getNewIcNo()+"\n" +
		 * "Password:"+SystemConstant.DEFAULT_PASSWORD+"\n" , memberInd.getEmail(), "Registration Succesfully",
		 * SystemConstant.SYSTEM_EMAIL);
		 */

		insertMemberTransaction(agreement.getAgreementId(), "Agreement Transfer. Agreement No. "
				+ agreement.getAgreetmentNo());

	}

	/*
	 * 
	 */
	public void doSaveMemberPointAdjustment(MemberPointEntitle memberPointEntitle,	 String type,User user ) throws Exception{
		if (memberPointEntitle.getAdjustTo()<=0){
			throw new BaseException("Adjustment Number must greater than 0.");
		}
		
		int total=0 ;
		if (type.equalsIgnoreCase("+")){
			  total = memberPointEntitle.getPoint()+ memberPointEntitle.getAdjustTo();
			
		}else{
			if (memberPointEntitle.getPoint()< memberPointEntitle.getAdjustTo()){
				throw new BaseException("Adjustment Number must greater than current point "+memberPointEntitle.getPoint());
			}
			  total = memberPointEntitle.getPoint()- memberPointEntitle.getAdjustTo();
			 
		}
		memberPointEntitle.setModifiedBy(user);
		memberPointEntitle.setModifiedDate(new Date());
		memberPointEntitle.setPoint(total);
		dao.update(memberPointEntitle);
		insertMemberTransaction(memberPointEntitle.getAgreement().getAgreementId(), "Point Adjustment. Agreement No "
				+ memberPointEntitle.getAgreement().getAgreetmentNo() + " point category " + 
				memberPointEntitle.getPointCategory().getName()+" had been adjusted " + type + " " + memberPointEntitle.getAdjustTo()  );

	}
	
	/**
	 * validate and save
	 */
	public void reserveMemberPoint(org.hgvc.webapp.ets.bo.Package bookingPackage, String agreementNo, Integer year,
			int weekendPoint, int weekdayPoint) throws BaseException {
		// TODO Auto-generated method stub
		List<MemberPointEntitle> lists;
		try {
			lists = dao.getValidMemberPointEntitleList(agreementNo, year);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "validateMemberPoint2" }));
		}
		for (MemberPointEntitle entitle : lists) {
			if (entitle.getReservedPoint() == null)
				entitle.setReservedPoint(0);
			if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWePointCate().getCode())) {
				if ((weekendPoint + entitle.getReservedPoint()) > entitle.getPoint()) {
					throw new BaseException("Point not enough. Your " + entitle.getPointCategory().getName()
							+ " point is only " + (entitle.getPoint() - entitle.getReservedPoint())
							+ " but it requires " + weekendPoint + ".");
				} else {
					entitle.setReservedPoint(entitle.getReservedPoint() + weekendPoint);
				}
			} else if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWdPointCate().getCode())) {
				if ((weekdayPoint + entitle.getReservedPoint()) > entitle.getPoint()) {
					throw new BaseException("Point not enough. Your " + entitle.getPointCategory().getName()
							+ " point is only " + (entitle.getPoint() - entitle.getReservedPoint())
							+ " but it requires " + weekdayPoint + ".");
				} else {
					entitle.setReservedPoint(entitle.getReservedPoint() + weekdayPoint);
				}
			} else {
				throw new BaseException("No such point code - " + entitle.getPointCategory().getCode());
			}

			entitle.setModifiedDate(new Date());

			try {
				dao.update(entitle);
			} catch (Exception e) {
				e.printStackTrace();
				throw new BaseException(SpringUtils.getMessage("error.invoke.method",
						new Object[] { "validateMemberPoint2" }));

			}
		}

	}

	public void cancelMemberPoint2(MemberBooking memberBooking) throws BaseException {
		org.hgvc.webapp.ets.bo.Package bookingPackage = memberBooking.getBookingPackage();
		String agreementNo = memberBooking.getAgreementNo();
		Integer year = memberBooking.getYear();

		List<MemberPointEntitle> lists;
		try {
			lists = dao.getValidMemberPointEntitleList(agreementNo, year);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BaseException(SpringUtils
					.getMessage("error.invoke.method", new Object[] { "cancelMemberPoint2" }));
		}
		for (MemberPointEntitle entitle : lists) {
			if (entitle.getReservedPoint() == null)
				entitle.setReservedPoint(0);
			if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWePointCate().getCode())) {
				entitle.setReservedPoint(entitle.getReservedPoint() - memberBooking.getWeekendPoint());
			} else if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWdPointCate().getCode())) {
				entitle.setReservedPoint(entitle.getReservedPoint() - memberBooking.getWeekdayPoint());
			}

			entitle.setModifiedDate(new Date());
			entitle.setModifiedBy(memberBooking.getModifiedBy());
			try {
				dao.update(entitle);
			} catch (Exception e) {
				e.printStackTrace();
				throw new BaseException(SpringUtils.getMessage("error.invoke.method",
						new Object[] { "cancelMemberPoint2" }));

			}
		}

	}

	public void deductMemberPoint2(MemberBooking memberBooking) throws BaseException {
		org.hgvc.webapp.ets.bo.Package bookingPackage = memberBooking.getBookingPackage();
		String agreementNo = memberBooking.getAgreementNo();
		Integer year = memberBooking.getYear();

		List<MemberPointEntitle> lists;
		try {
			lists = dao.getValidMemberPointEntitleList(agreementNo, year);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "validateMemberPoint2" }));
		}
		for (MemberPointEntitle entitle : lists) {
			if (entitle.getReservedPoint() == null)
				entitle.setReservedPoint(0);
			if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWePointCate().getCode())) {
				entitle.setReservedPoint(entitle.getReservedPoint() - memberBooking.getWeekendPoint());
				entitle.setPoint(entitle.getPoint() - memberBooking.getWeekendPoint());
			} else if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWdPointCate().getCode())) {
				entitle.setReservedPoint(entitle.getReservedPoint() - memberBooking.getWeekdayPoint());
				entitle.setPoint(entitle.getPoint() - memberBooking.getWeekdayPoint());
			}

			entitle.setModifiedDate(new Date());
			entitle.setModifiedBy(memberBooking.getModifiedBy());
			try {
				dao.update(entitle);
			} catch (Exception e) {
				e.printStackTrace();
				throw new BaseException(SpringUtils
						.getMessage("error.invoke.method", new Object[] { "confirmBooking" }));

			}
		}

	}

	public void reverseConfirmMemberPoint(MemberBooking memberBooking) throws BaseException {
		org.hgvc.webapp.ets.bo.Package bookingPackage = memberBooking.getBookingPackage();
		String agreementNo = memberBooking.getAgreementNo();
		Integer year = memberBooking.getYear();

		List<MemberPointEntitle> lists;
		try {
			lists = dao.getValidMemberPointEntitleList(agreementNo, year);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method",
					new Object[] { "validateMemberPoint2" }));
		}
		for (MemberPointEntitle entitle : lists) {
			if (entitle.getReservedPoint() == null)
				entitle.setReservedPoint(0);
			if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWePointCate().getCode())) {
				entitle.setPoint(entitle.getPoint() + memberBooking.getWeekendPoint());
			} else if (entitle.getPointCategory().getCode().equalsIgnoreCase(bookingPackage.getWdPointCate().getCode())) {
				entitle.setPoint(entitle.getPoint() + memberBooking.getWeekdayPoint());
			}

			entitle.setModifiedDate(new Date());
			entitle.setModifiedBy(memberBooking.getModifiedBy());
			try {
				dao.update(entitle);
			} catch (Exception e) {
				e.printStackTrace();
				throw new BaseException(SpringUtils
						.getMessage("error.invoke.method", new Object[] { "confirmBooking" }));

			}
		}

	}

	public void saveAgentAgreementTransfer(Agent agent, Agent toAgent, List<Agreement> agreements, User user)
			throws Exception {
		if (agent.getAgentId().equalsIgnoreCase(toAgent.getAgentId())) {
			throw new BaseException("You are transferring agreement back to same agent.");
		}
		List<Agreement> agreementToTransfer = new ArrayList<Agreement>();
		int count = 0;
		for (Agreement agreement : agreements) {
			if (agreement.isMarkAsAction()) {
				agreement.getMember().setAgent(toAgent);
				agreement.getMember().setModifiedBy(user);
				agreement.getMember().setModifiedDate(new Date());

				dao.update(agreement.getMember());
				AgreementTransferlog agreementTransferlog = new AgreementTransferlog();
				agreementTransferlog.setFromAgent(agent);
				agreementTransferlog.setToAgent(toAgent);
				agreementTransferlog.setDate(new Date());
				dao.save(agreementTransferlog);
				count++;
			}

		}
		if (count < 1) {
			throw new BaseException("Please select atleast one agreement.");
		}
	}

	public void setFinanceDao(FinanceHbmDao financeDao) {
		this.financeDao = financeDao;
	}

	public void updateAgreementNewCommission(List<Agreement> agreements, CommissionSchemaPaymentRange range, int month,
			int year) throws Exception {
		for (Agreement agreement : agreements) {
			double newCommissionCost = 0;
			double newCommissionPercentage = 0;

			if (range != null) {
				newCommissionCost = range.getPercent() / 100 * agreement.getMembership().getMembershipFee();
				newCommissionPercentage = range.getPercent();
			}

			if (agreement.getAgentPreCommissionOutstdMonth() == month
					&& agreement.getAgentPreCommissionOutstdYear() == year) {
				agreement.setAgentCommissionOutstanding(agreement.getAgentPreCommissionOutstanding());

			}
			if (agreement.getAgentPreCommissionOutstdMonth() == 0 && agreement.getAgentPreCommissionOutstdYear() == 0) {
				// new agreement
				if (agreement.getStatus().equalsIgnoreCase(AgreementConstant.AGREEMENT_STATUS_TERMINATED)) {
					agreement.setAgentCommissionOutstanding(0d);
					// agreement.setAgentCommissionCost(0d);
					agreement.setAgentCommissionPercentage(0d);
				} else {
					agreement.setAgentCommissionOutstanding(newCommissionCost);
					agreement.setAgentCommissionCost(newCommissionCost);
					agreement.setAgentCommissionPercentage(newCommissionPercentage);
				}
			} else {
				if (agreement.getStatus().equalsIgnoreCase(AgreementConstant.AGREEMENT_STATUS_TERMINATED)
						&& "Y".equalsIgnoreCase(agreement.getAffectCommission())) {
					// agreement.outstanding = -(commisionCost-agreement.outstanding)
					// commisionCost=0
					agreement.setAgentCommissionOutstanding(-(agreement.getAgentCommissionCost() - agreement
							.getAgentCommissionOutstanding()));
					// agreement.setAgentCommissionCost(0d);
				} else {
					// agreement.outstanding = newCommsionCosst-commisionCost)+agreement.outstanding;
					// commisionCost=newCommsionCosst
					// agreement.CommsionPercentage = newCommsionPercentage
					agreement.setAgentCommissionOutstanding(newCommissionCost - agreement.getAgentCommissionCost()
							+ agreement.getAgentCommissionOutstanding());
					agreement.setAgentCommissionCost(newCommissionCost);
					agreement.setAgentCommissionPercentage(newCommissionPercentage);
				}
			}
			agreement.setModifiedDate(new Date());
			agreement.setModifiedBy(SystemConstant.SYSTEM_USER);
			dao.update(agreement);
		}
	}

	public void saveAgentCommission(Agent agent, int month, int year) throws Exception {

		// agreement.setAgentCommissionOutstanding(agreement.getAgentPreCommissionOutstanding());
		agreementDao.deleteAgentCommission(agent.getAgentId(), month, year);

		List<Agreement> agreements = agreementDao.getAgreementForCommOutstanding(agent.getAgentId());
		for (Agreement agreement : agreements) {

			double totalPaidComm = agreementDao.getTotalCommPaid(agreement.getAgreementId());

			double collectionThisMonth = financeDao.getTotalPaidInstallment(agreement.getAgreementId(), month, year);
			double thisMonthPayableComm = agent.getPaymentSchema().getPaymentPercent() / 100 * collectionThisMonth;
			double thisMonthCommission = thisMonthPayableComm;
			if (thisMonthCommission > agreement.getAgentCommissionOutstanding()) {
				thisMonthCommission = agreement.getAgentCommissionOutstanding();
			}
			AgentCommission agentCommission = new AgentCommission();

			agentCommission.setAccumulateAmount(totalPaidComm + thisMonthCommission);
			agentCommission.setMonth(month);
			agentCommission.setYear(year);

			agentCommission.setPaid(thisMonthCommission);
			agentCommission.setSale(agreement.getMembership().getMembershipFee());
			agentCommission.setCommission(agreement.getAgentCommissionPercentage());
			agentCommission.setMaxPayable(agreement.getAgentCommissionCost());
			agentCommission.setCollection(collectionThisMonth);
			agentCommission.setPayable(thisMonthPayableComm);
			agentCommission.setOutstanding(agreement.getAgentCommissionCost() - (totalPaidComm + thisMonthCommission));
			agentCommission.setIsDeleted(CommonConstant.NOT_DELETED);
			agentCommission.setCreatedBy(SystemConstant.SYSTEM_USER);
			agentCommission.setCreatedDate(new Date());
			agentCommission.setAgent(agent);
			agentCommission.setAgreement(agreement);
			agreement.setAgentCommissionOutstanding(agreement.getAgentCommissionOutstanding() - thisMonthCommission);

			int agreementMonth = DateUtil.setTime(agreement.getAgreetmentDate()).get(Calendar.MONTH);
			agreementMonth++;// check whether this month new agreement. prevent update to precommission

			if (agreement.getAgentPreCommissionOutstdMonth() != month && agreementMonth != month) {

				agreement.setAgentPreCommissionOutstanding(agreement.getAgentCommissionOutstanding());
				agreement.setAgentPreCommissionOutstdMonth(month);
				agreement.setAgentPreCommissionOutstdYear(year);

			}
			agreement.setModifiedBy(SystemConstant.SYSTEM_USER);
			agreement.setModifiedDate(new Date());
			dao.update(agreement);
			dao.save(agentCommission);
		}

		List<Agreement> agreementsOverPay = agreementDao.getAgreementForCommOverPay(agent.getAgentId());
		for (Agreement agreement : agreementsOverPay) {

			// double totalPaidComm =agreement.getAgentCommissionCost()- agreement.getAgentCommissionOutstanding();
			double collectionThisMonth = financeDao.getTotalPaidInstallment(agreement.getAgreementId(), month, year);

			AgentCommission agentCommission = new AgentCommission();
			agentCommission.setMonth(month);
			agentCommission.setYear(year);

			agentCommission.setAccumulateAmount(0d);
			agentCommission.setMaxPayable(agreement.getAgentCommissionCost());
			agentCommission.setPaid(agreement.getAgentCommissionOutstanding());
			agentCommission.setSale(agreement.getMembership().getMembershipFee());
			agentCommission.setCollection(collectionThisMonth);
			agentCommission.setOutstanding(0d);
			agentCommission.setCommission(0d);
			agentCommission.setCreatedBy(SystemConstant.SYSTEM_USER);
			agentCommission.setCreatedDate(new Date());
			agentCommission.setIsDeleted(CommonConstant.NOT_DELETED);
			agentCommission.setAgent(agent);
			agentCommission.setAgreement(agreement);

			agreement.setModifiedBy(SystemConstant.SYSTEM_USER);
			agreement.setModifiedDate(new Date());
			agreement.setAgentCommissionOutstanding(0d);

			int agreementMonth = DateUtil.setTime(agreement.getAgreetmentDate()).get(Calendar.MONTH);
			agreementMonth++;// check whether this month new agreement. prevent update to precommission

			if (agreement.getAgentPreCommissionOutstdMonth() != month && agreementMonth != month) {

				agreement.setAgentPreCommissionOutstanding(agreement.getAgentCommissionOutstanding());
				agreement.setAgentPreCommissionOutstdMonth(month);
				agreement.setAgentPreCommissionOutstdYear(year);

			}

			dao.update(agreement);
			dao.save(agentCommission);
		}

	}

	public void setAgreementDao(AgreementHbmDao agreementDao) {
		this.agreementDao = agreementDao;
	}

	/**
	 * 
	 * @param partnerProduct
	 * @param fromDate
	 * @param toDate
	 * @param numberOfRoom
	 * @param type + -
	 * @throws Exception
	 */
	public void saveInventory(PartnerProduct partnerProduct, Date fromDate, Date toDate, int numberOfRoom, String type,
			User user) throws Exception {
		Date curentDate = fromDate;

		while (com.j6.framework.util.DateUtil.isBetweenDate(curentDate, fromDate, toDate)) {
			List<Inventory> inventories = dao.getInventory(curentDate, partnerProduct.getPartnerProductId());
			if (CollectionUtil.isNotEmpty(inventories)) {
				if (type.equalsIgnoreCase("-")) {
					if (inventories.get(0).getNoOfRoom() < numberOfRoom) {
						throw new BaseException("There is only " + inventories.get(0).getNoOfRoom()
								+ " number of room available.");
					} else {
						Inventory inventory = inventories.get(0);

						inventory.setModifiedBy(user);
						inventory.setModifiedDate(new Date());
						inventory.setNoOfRoom(inventory.getNoOfRoom() - numberOfRoom);
						inventory.setTotalRoom(inventory.getTotalRoom() - numberOfRoom);
						dao.update(inventory);
					}
				} else {
					Inventory inventory = inventories.get(0);

					inventory.setModifiedBy(user);
					inventory.setModifiedDate(new Date());
					inventory.setNoOfRoom(inventory.getNoOfRoom() + numberOfRoom);
					inventory.setTotalRoom(inventory.getTotalRoom() + numberOfRoom);
					dao.update(inventory);
				}
			} else {
				if (type.equalsIgnoreCase("-")) {
					throw new BaseException("There is not inventory record to be deducted.");
				} else {
					Inventory inventory = new Inventory();
					inventory.setCreatedBy(user);
					inventory.setCreatedDate(new Date());
					inventory.setModifiedBy(user);
					inventory.setModifiedDate(new Date());
					inventory.setNoOfRoom(numberOfRoom);
					inventory.setPartnerProduct(partnerProduct);
					inventory.setResortDate(curentDate);
					inventory.setTotalRoom(numberOfRoom);
					dao.save(inventory);
				}
			}
			curentDate = com.j6.framework.util.DateUtil.addDate(curentDate, 1);
		}
	}

	public void saveReshedule(Agreement agreement, String installmentSchemaId, User user) throws Exception {
		InstallmentSchema installmentSchema = (InstallmentSchema) dao.getObject(InstallmentSchema.class,
				installmentSchemaId);
		double outstanding = ((agreement.getInstallmentSchema().getMonth() - agreement.getMemberScheduleScheme()
				.getInstalledMonth()) * (agreement.getMemberScheduleScheme().getTotalPrice() / agreement
				.getInstallmentSchema().getMonth()));

		if (installmentSchema.getMonth() != 1) {
			if (agreement.getMemberScheduleScheme().getInstalledMonth() + installmentSchema.getMonth() > agreement
					.getMembership().getMembershipCategory().getMaxInstallmentMonth()) {
				throw new BaseException("New installment month ("
						+ (agreement.getMemberScheduleScheme().getInstalledMonth() + installmentSchema.getMonth())
						+ ")more than maximum installment month( "
						+ agreement.getMembership().getMembershipCategory().getMaxInstallmentMonth() + ").");
			}

			MemberScheduleScheme memberScheduleScheme = new MemberScheduleScheme();
			memberScheduleScheme.setAgreement(agreement);
			memberScheduleScheme.setCreatedBy(user);
			memberScheduleScheme.setCreatedDate(new Date());
			memberScheduleScheme.setInstalledMonth(0);
			memberScheduleScheme.setInterestRate(installmentSchema.getInterestRate());
			memberScheduleScheme.setModifiedBy(user);
			memberScheduleScheme.setModifiedDate(new Date());
			// memberScheduleScheme.setOutstanding(outstanding);
			memberScheduleScheme.setTotalPrice(outstanding);
			dao.save(memberScheduleScheme);

			agreement.setInstallmentSchema(installmentSchema);
			agreement.setMemberScheduleScheme(memberScheduleScheme);
			agreement.setModifiedBy(user);
			agreement.setModifiedDate(new Date());
			dao.update(agreement);

			MicTask mic = new MicTask();
			mic.setCreatedBy(user);
			mic.setCreatedDate(new Date());
			mic.setModifiedBy(user);
			mic.setModifiedDate(new Date());
			mic.setDate(new Date());
			mic.setMember(agreement.getMember());
			mic.setDesc("Agreement " + agreement.getAgreetmentNo() + " reschedule to " + installmentSchema.getMonth()
					+ " months. Principal outstading RM" + outstanding + ". Monthly Interest rate "
					+ installmentSchema.getInterestRate() + "%");
			dao.save(mic);
		} else {
			saveFullPaymentReschedule(agreement, user);
		}
	}

	public void saveFullPaymentReschedule(Agreement agreement, User thisUser) throws Exception {
		double outstanding = ((agreement.getInstallmentSchema().getMonth() - agreement.getMemberScheduleScheme()
				.getInstalledMonth()) * (agreement.getMemberScheduleScheme().getTotalPrice() / agreement
				.getInstallmentSchema().getMonth()));

		ActionBulletin ab = new ActionBulletin();
		ab.setActionCode("Agreement " + agreement.getAgreetmentNo() + " reschedule full payment Amount RM"
				+ outstanding);
		ab.setActionBean(MemberAgreementTransferBean.BEAN_NAME);
		ab.setActionMethod(MemberAgreementTransferBean.NAV_ACTION_BULETIN);
		ab.setActionParam1(agreement.getAgreementId());
		ab.setActionParam2(agreement.getMember().getMembershipNo());
		ab.setCreatedBy(thisUser);
		ab.setCreatedDate(new Date());
		ab.setIsDeleted(CommonConstant.NOT_DELETED);
		ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
		ab.setActionNo(SystemUtil.getUniqueCode());
		ab.setUser(thisUser);
		systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);

		Finance finance = new Finance();
		finance.setCreatedBy(thisUser);
		finance.setCreatedDate(new Date());
		finance.setIsDeleted(CommonConstant.NOT_DELETED);
		finance.setAgreement(agreement);
		dao.save(finance);

		String newInvoiceNo = financeService.getDocumentNo(CommonConstant.DOC_TYPE_INVOICE);

		// generate invoice
		Invoice invoice = new Invoice();
		invoice.setCreatedBy(thisUser);
		invoice.setCreatedDate(new Date());
		invoice.setInvoiceAmount(outstanding);
		invoice.setInvoiceDate(new Date());
		invoice.setInvoiceNo(newInvoiceNo);
		invoice.setIsDeleted(CommonConstant.NOT_DELETED);
		invoice.setRefId(agreement.getAgreementId());
		invoice.setFinance(finance);
		// invoice.setPayment(payment); TODO why got invoice.payment. invoice should have many invoice. why?
		dao.save(invoice);

		// generate invoice dtl
		InvoiceDtl invoiceDtl = new InvoiceDtl();
		invoiceDtl.setInvoice(invoice);
		invoiceDtl.setCreatedBy(thisUser);
		invoiceDtl.setCreatedDate(new Date());
		invoiceDtl.setIsDeleted(CommonConstant.NOT_DELETED);
		invoiceDtl.setItemAmount(invoice.getInvoiceAmount());
		invoiceDtl.setItemType(CommonConstant.INVOICE_TYPE_INSTALLMENT_FULLPAYMENT);
		invoiceDtl.setStatus(CommonConstant.INVOICE_STATUS_ACTIVE);
		invoiceDtl.setItemDesc(CommonConstant.INVOICE_INSTALLMENT_FULL_DESC);
		invoiceDtl.setPaidAmount(0d);
		dao.save(invoiceDtl);

		MicTask mic = new MicTask();
		mic.setCreatedBy(thisUser);
		mic.setCreatedDate(new Date());
		mic.setModifiedBy(thisUser);
		mic.setModifiedDate(new Date());
		mic.setDate(new Date());
		mic.setMember(agreement.getMember());
		mic.setDesc("Agreement " + agreement.getAgreetmentNo() + " reschedule full payment Amount RM" + outstanding);
		dao.save(mic);
	}

	public List<MicTask> getMicTask(String memberId) throws Exception {
		return dao.getMicTask(memberId);
	}

	public void doaAccruedDate(MemberPointEntitle c, Date accruedDate, User user) throws Exception {
		Calendar calendar = com.j6.framework.util.DateUtil.setTime( c.getExpiryDate() );
		calendar.add(Calendar.YEAR, 1 );
		SimpleDateFormat s = new SimpleDateFormat("dd/MM/yyyy");
		 
		if (calendar.before(accruedDate)){
			 throw new BaseException("Accrued date can not more than one year from expired date.");
		}
		
		if (c.getAccruedDate()==null){
			 throw new BaseException("Please key in accrued date.");
		}
		
		 if (c.getExpiryDate().after(accruedDate) || com.j6.framework.util.DateUtil.isBetweenDate(accruedDate, c.getExpiryDate(), c.getExpiryDate())){
			 throw new BaseException("Your accrued date is earlier than expired date.");
		 }
	
		 Calendar within30Day = com.j6.framework.util.DateUtil.setTime(c.getExpiryDate());
		 within30Day.add(Calendar.MONTH, -9);
		 Date within30DayDate = within30Day.getTime();
		 within30DayDate = com.j6.framework.util.DateUtil.truncateTime(within30DayDate);
		  
		 if (!new Date().before(within30DayDate)){
			 throw new BaseException("Current date already over 3 months("+s.format(within30DayDate)+") from entitlement date.");
		 }
		 c.setExpiredDateBeforeAccrued(c.getExpiryDate());
		 c.setExpiryDate(accruedDate);
		 c.setModifiedBy(user);
		 c.setModifiedDate(new Date());
		
		 dao.update(c);
		 insertMemberTransaction(c.getAgreement().getAgreementId(), "Accrued Vacation. From Date "+  s.format(c.getExpiredDateBeforeAccrued()) +" to " +
		 		s.format(accruedDate));
		 
	}

	public void doSavePreAdvanceEntitlement(Agreement agreement, User user) throws Exception {
		 
		List<MemberPointEntitle>memberPointEntitles = dao.getHibernateTemplate().loadAll(MemberPointEntitle.class);
		int nextEntitlementYear=0;
		MemberPointEntitle latestMemberPointEntitle=null;
		Date nextEntitlementExpiredDate;
		
		for(MemberPointEntitle m : memberPointEntitles){
			if (nextEntitlementYear<m.getYear()){
				nextEntitlementYear =  m.getYear();
				latestMemberPointEntitle = m;
			}
		}
  
	 	nextEntitlementYear = nextEntitlementYear+2;
		Calendar cc = DateUtil.setTime(latestMemberPointEntitle.getExpiryDate());
		cc.add(2, Calendar.MONTH);
		nextEntitlementExpiredDate = cc.getTime();
		 
		Calendar c = DateUtil.setTime(agreement.getAgreetmentDate());
		c.add(Calendar.YEAR, agreement.getMembership().getMembershipTerm()-1);
		Date lastEntitlementDate = c.getTime();
		
		if (!nextEntitlementExpiredDate.before(lastEntitlementDate) && !com.j6.framework.util.DateUtil.isBetweenDate( lastEntitlementDate,nextEntitlementExpiredDate,nextEntitlementExpiredDate )){
			throw new BaseException("Advance entitlement is over agreement term "+agreement.getMembership().getMembershipTerm());
		}
		
		agreement.setAdvancedYear(nextEntitlementYear);
		agreement.setModifiedBy(user);
		agreement.setModifiedDate(new Date());
		dao.merge(agreement);
		
		//
		
		ActionBulletin ab = new ActionBulletin();
		ab.setActionCode("Advance Entitlement for agreement" + agreement.getAgreetmentNo() + " on year "+nextEntitlementYear);
		ab.setActionBean(MemberAgreementTransferBean.BEAN_NAME);
		ab.setActionMethod(MemberAgreementTransferBean.NAV_ACTION_BULETIN);
		ab.setActionParam1(agreement.getAgreementId());
		ab.setActionParam2(agreement.getMember().getMembershipNo());
		ab.setCreatedBy(user);
		ab.setCreatedDate(new Date());
		ab.setIsDeleted(CommonConstant.NOT_DELETED);
		ab.setType(ActionBulletinConstant.AB_ACTION_TYPE);
		ab.setActionNo(SystemUtil.getUniqueCode());
		ab.setUser(user);
		systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);

		Finance finance = new Finance();
		finance.setCreatedBy(user);
		finance.setCreatedDate(new Date());
		finance.setIsDeleted(CommonConstant.NOT_DELETED);
		finance.setAgreement(agreement);
		dao.save(finance);

		String newInvoiceNo = financeService.getDocumentNo(CommonConstant.DOC_TYPE_INVOICE);

		// generate invoice
		Invoice invoice = new Invoice();
		invoice.setCreatedBy(user);
		invoice.setCreatedDate(new Date());
		invoice.setInvoiceAmount(agreement.getMembership().getAnnualMaintenance());
		invoice.setInvoiceDate(new Date());
		invoice.setInvoiceNo(newInvoiceNo);
		invoice.setIsDeleted(CommonConstant.NOT_DELETED);
		invoice.setRefId(agreement.getAgreementId());
		invoice.setFinance(finance);
		// invoice.setPayment(payment); 
		dao.save(invoice);

		// generate invoice dtl
		InvoiceDtl invoiceDtl = new InvoiceDtl();
		invoiceDtl.setInvoice(invoice);
		invoiceDtl.setCreatedBy(user);
		invoiceDtl.setCreatedDate(new Date());
		invoiceDtl.setIsDeleted(CommonConstant.NOT_DELETED);
		invoiceDtl.setItemAmount(invoice.getInvoiceAmount());
		invoiceDtl.setItemType(CommonConstant.INVOICE_TYPE_ANNUAL_MAINTENANCE);
		invoiceDtl.setStatus(CommonConstant.INVOICE_STATUS_ACTIVE);
		invoiceDtl.setItemDesc(CommonConstant.INVOICE_TYPE_ANNUAL_MAINTENANCE_DESC);
		invoiceDtl.setPaidAmount(0d);
		dao.save(invoiceDtl);

 
	}
	
	public void saveTerminateProspec(Member member, User user) throws Exception{
 
		
//
	    Agreement agreement = dao.getAgreementByMemberId(member.getMemberId());
	    agreement.setStatus(AgreementConstant.AGREEMENT_STATUS_TERMINATED);
	    agreement.setModifiedBy(user);
	    agreement.setModifiedDate(new Date());
	    dao.update(agreement);
	    
		if (member.getMemberType().equalsIgnoreCase(CommonConstant.MEMBER_TYPE_IND)){
			MemberInd memberInd = getMemberIndByMemberId(member.getMemberId());
			member.setName(memberInd.getNameAsIcPassport());
		}else{
			MemberComp memberComp = getMemberCompByMemberId(member.getMemberId());
			member.setName(memberComp.getCompName());
		}
		
		ActionBulletin ab = new ActionBulletin();
		ab.setActionCode("Terminate Prospect.Member name "+member.getName()+". Membership No. "+agreement.getMember().getMembershipNo()+". Refund is needed.");
		ab.setActionBean(MemberAgreementTransferBean.BEAN_NAME);
		ab.setActionMethod(MemberAgreementTransferBean.NAV_ACTION_BULETIN);
		ab.setActionParam1(agreement.getAgreementId());
		ab.setActionParam2(agreement.getMember().getMembershipNo());
		ab.setCreatedBy(user);
		ab.setCreatedDate(new Date());
		ab.setIsDeleted(CommonConstant.NOT_DELETED);
		ab.setType(ActionBulletinConstant.AB_ACTION_TYPE);
		ab.setActionNo(SystemUtil.getUniqueCode());
		ab.setUser(user);
		systemService.createActionBulletinByRoles(ab, SystemConstant.FINANCE_ADMIN_ROLE);

		terminateProcService.terminateProspect(member, user);
		
	}

	public void setTerminateProcService(TerminateProcService terminateProcService) {
		this.terminateProcService = terminateProcService;
	}

}
